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.
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
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:
Finally realize level pages with different levels according to Jump with different permissions.
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
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>
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>
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()); } }
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!