Home  >  Article  >  Java  >  How to use SpringBoot+SpringSecurity to implement authorization authentication based on real data

How to use SpringBoot+SpringSecurity to implement authorization authentication based on real data

王林
王林forward
2023-05-13 19:34:20942browse

(1) Overview

Spring Security is a powerful and highly customizable authentication and access control framework. Spring Security mainly does two things, authentication and authorization. I have written a blog about SpringSecurity before, but at that time I only introduced a case based on mock data. In this issue, I will introduce the implementation of authentication and authorization based on real data.

(2) Preliminary project construction

In order to better demonstrate SpringSecurity, we first build a simple web project. Introduce thymeleaf dependency

<dependency>
    <groupid>org.springframework.boot</groupid>
    <artifactid>spring-boot-starter-thymeleaf</artifactid>
</dependency>
<dependency>
    <groupid>org.thymeleaf</groupid>
    <artifactid>thymeleaf-spring5</artifactid>
</dependency>
<dependency>
    <groupid>org.thymeleaf.extras</groupid>
    <artifactid>thymeleaf-extras-java8time</artifactid>
</dependency>

Create a new login page, a homepage, and several different levels of display pages: login.html

nbsp;html>


    <meta>
    <title>登陆页</title>


<div>
    <form>
        <h3>登陆页</h3>
        <input>
        <input>
        <button>登陆</button>
    </form>
</div>

index.html

nbsp;html>


    <meta>
    <title>首页</title>


<div>
    <h3>首页</h3>
    <a>登陆</a>
    <div>
        <div>
            <h4>level1</h4>
            <a>level-1-1</a>
            <hr>
            <a>level-1-2</a>
        </div>
        <div>
            <h4>level2</h4>
            <a>level-2-1</a>
            <hr>
            <a>level-2-2</a>
        </div>
        <div>
            <h4>level3</h4>
            <a>level-3-1</a>
            <hr>
            <a>level-3-2</a>
        </div>
    </div>
</div>

In addition, there are Several different levels of pages

How to use SpringBoot+SpringSecurity to implement authorization authentication based on real data

write their corresponding numbers in the body respectively.

nbsp;html>


    <meta>
    <title>Title</title>


level-1-1

Finally write a controller to receive the request:

@Controller
public class RouteController {

    @RequestMapping({"/","/index"})
    public String index(){
        return "index";
    }

    @RequestMapping("/login")
    public String toLogin(){
        return "login";
    }

    @RequestMapping("/level1/{id}")
    public String level1(@PathVariable("id")String id){
        return "level1/"+id;
    }
    @RequestMapping("/level2/{id}")
    public String level2(@PathVariable("id")String id){
        return "level2/"+id;
    }
    @RequestMapping("/level3/{id}")
    public String level3(@PathVariable("id")String id){
        return "level3/"+id;
    }
}

The final effect is as follows:

How to use SpringBoot+SpringSecurity to implement authorization authentication based on real data

Finally realize level pages with different levels according to Jump with different permissions.

How to use SpringBoot+SpringSecurity to implement authorization authentication based on real data

The background is implemented based on Mybatis and Mysql database, so in addition to introducing SpringSecurity dependencies, we also need to introduce Mybatis related dependencies:

<dependency>
    <groupid>org.springframework.boot</groupid>
    <artifactid>spring-boot-starter-security</artifactid>
</dependency>
<dependency>
    <groupid>org.springframework.boot</groupid>
    <artifactid>spring-boot-starter-jdbc</artifactid>
</dependency>
<dependency>
    <groupid>mysql</groupid>
    <artifactid>mysql-connector-java</artifactid>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupid>org.mybatis.spring.boot</groupid>
    <artifactid>mybatis-spring-boot-starter</artifactid>
    <version>2.1.3</version>
</dependency>

In the configuration file Add data source related information and Mybatis configuration:

spring.datasource.url=jdbc:mysql://localhost:3306/security?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

mybatis.mapper-locations=classpath:mapper/*.xml

(3) Implementation of authentication and authorization

3.1 Table structure design

Authentication and authorization in table design It should be divided into two tables, one table stores user information including passwords, etc., and the other table stores authorization information. Another table is needed to establish the association between users and authorization, giving the final table structure:

CREATE TABLE `roles` (
  `id` int(4) NOT NULL,
  `rolename` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `sysuser` (
  `id` int(4) NOT NULL,
  `username` varchar(255) NOT NULL,
  `password` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `user_role` (
  `id` int(4) NOT NULL,
  `user_id` int(4) DEFAULT NULL,
  `role_id` int(4) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Next is the entity class, Mapper interface and xml file for these three tables. You don’t need to look at the code. It mainly implements an operation of finding users and related permissions through user names:

@Data
public class Roles {
    private Integer id;
    private String roleName;
}

@Data
public class SysUser {
    private Integer id;
    private String userName;
    private String password;
    private List<roles> roles;
}</roles>

Mapper interface:

public interface UserMapper {
    public SysUser getUserByUserName(@Param("userName") String userName);
}

xml implementation:

<?xml  version="1.0" encoding="UTF-8" ?>
nbsp;mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper>
    <resultmap>
        <id></id>
        <result></result>
        <result></result>
        <collection>
            <result></result>
        </collection>
    </resultmap>
    <select>
        select sysuser.*,roles.rolename
        from sysuser
        LEFT JOIN user_role on sysuser.id= user_role.user_id
        LEFT JOIN roles on user_role.role_id=roles.id
        where username= #{userName}
    </select>
</mapper>

3.2 Authentication process

SpringSecurity’s authentication process is like this. First, find the user in the database through the user name or other unique ID. User The passwords are stored in asymmetric encryption. After obtaining the user, the password passed in from the front desk is encrypted and compared with the encrypted fields in the database to pass the authentication.

The first step in the above process is to find the user through the user name, which needs to be implemented through the Service service, and this Service service needs to inherit the UserDetailsService interface in SpringSecurity. This interface returns a SpringSecurity User object.

@Service
public class UserService implements UserDetailsService {

    @Resource
    private UserMapper userMapper;
    //根据用户名找到对应的用户信息
    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        SysUser sysUser = userMapper.getUserByUserName(s);
        if (sysUser!=null){
            List<grantedauthority> roles=new ArrayList();
            sysUser.getRoles().stream().forEach(x->{
                roles.add(new SimpleGrantedAuthority(x.getRoleName()));
            });
            return new User(sysUser.getUserName(),sysUser.getPassword(),roles);
        }
        throw new UsernameNotFoundException("用户未找到");
    }
}</grantedauthority>

3.3 Security interception configuration

After completing the above steps, start configuring Security. Write a configuration method SecurityConfig. The code level is very simple. The authentication is passed into the userService object and the database will be automatically Compare the password retrieved from the server with the password passed from the front end. At the same time, the roles collection is also passed in the userService, and different permissions can be attached to different pages at the authorization point.

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserService userService;
    //授权
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //首页所有人都能访问,level页面只有有权限的人才能访问
        http.authorizeRequests()
                .antMatchers("/").permitAll()
                .antMatchers("/level1/**").hasRole("vip1")
                .antMatchers("/level2/**").hasRole("vip2")
                .antMatchers("/level3/**").hasRole("vip3");
        //没有权限默认跳到登陆页,默认会重定向到/login
        http.formLogin();
    }

    //认证
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService).passwordEncoder(new BCryptPasswordEncoder());

    }
}

3.4 Other points to note

The password encryption method I use during authentication is BCryptPasswordEncoder, so the password stored in the database also needs to be encrypted. The common way is to pass it during registration Encrypt the password and store it in the database in the same way:

String password="xxx";
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
String encode=bCryptPasswordEncoder.encode(password);

The above is the detailed content of How to use SpringBoot+SpringSecurity to implement authorization authentication based on real data. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:yisu.com. If there is any infringement, please contact admin@php.cn delete