catalogs
Introduction to Spring Security
Spring Security Certification_Project Build
Spring Security Certification_In-Memory Certification
Spring Security Certification_UserDetailsService
Spring Security Certification_Database Certification
Spring Securityaccreditation_PasswordEncoder
Spring Security Certification_Custom Login Page
Spring Security Certification_Session Management
Spring Security Authentication_Handling of Successful Authentication
Spring Security Authentication_Handling after Authentication Failure
Spring Security Authentication_Exit Login
Spring Security Authentication_Exit Success Handler
Spring Security Certification_Remember Me
Spring Security Authorization_RBAC
Spring Security Authorization_Permission_Table Design
Spring Security Authorization_Writing Query Permission Methods
Spring Security Authorization_Configuration Class Setting Access Control
Spring Security Authorization_Custom Access Control Logic
Spring Security Authorization_Annotation Setting Access Control
Spring Security Authorization_Access Control on the Front End
Spring Security Authorization_403 Handling Scheme
Introduction to Spring Security
Spring Security is a security services framework provided by the Spring project team, with core functionality including authentication and authorization. It provides declarative securityaccess controlThe function reduces the need to write large amounts of repetitive code for system security.
accreditation
Authentication means that the system determines whether the user's identity is legal or not; if it is legal, the user can continue to access the system; if it is not legal, the user will be denied access. Common user authentication methods include: user name and password login, QR code login, cell phone SMS login, facial recognition authentication, fingerprint authentication, etc. Authentication is to protect the privacy data and resources of the system, and the user's identity is legitimate to access the resources of the system. Authentication is to protect the system's private data and resources, and users can only access the system's resources if their identities are legal.
authorizations
authorization that isAfter certificationIn this way, the user's access to resources is controlled according to the user's privileges, and access is denied if the user has the privileges to access the resources, and denied if the user does not have the privileges to access the resources. For example, in some video websites, ordinary users only have the right to watch free videos after logging in, while VIP users will be given the right to watch VIP videos after logging in. Authentication is to ensure the legitimacy of the user's identity, while authorization is to divide the private data at a finer granularity and control different users to access different resources.
As an example: Authentication is when the company gate recognizes that you, as an employee, have access to the company, while authorization is when you, as the company's accountant, have access to the finance room, view the accounts, and work with the financial data.
Spring Security Certification_Project Build
Next, let's build a Spring Security project.
1. Prepare a Mysql database named mysecurity.
2, create a SpringBoot project, add dependencies
<!-- SpringMVC --> <dependency> <groupId></groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--Thymeleaf--> <dependency> <groupId></groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <!--Spring Security--> <dependency> <groupId></groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <! -- Mysql driver --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <!-- MyBatisPlus --> <dependency> <groupId></groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.0</version> </dependency> <!-- lombok --> <dependency> <groupId></groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!-- junit --> <dependency> <groupId></groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>3, write configuration files for SpringBoot project
server: port: 80 # Log format logging: pattern: console: '%d{HH:mm:} %clr(%-5level) --- [%-15thread] %cyan(%-50logger{50}):%msg%n' # Data sources spring: datasource: driver-class-name: url: jdbc:mysql:///mysecurity?serverTimezone=UTC username: root password01: root4, in the template folder to write the main page of the project
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>main page</title> </head> <body> <h1>main page</h1> </body> </html>5. Writing access page controllers
@Controller public class PageController { @RequestMapping("/{page}") public String showPage(@PathVariable String page){ return page; } }Start the project and visit the main project page at http://localhost/main and the project will automatically jump to alogin pageThis means that Spring Security has enabled authentication. This means that Spring Security has enabled authentication and you can't access all resources without logging in. This page is the login page that comes with Spring Security. This page is the login page that comes with Spring Security. We use user as the username and the string in the console as the password to log in, and then jump to the main page of the project after a successful login. In subsequent lessons, we will explain how to customize the login page, login logic, and so on in real development.
Spring Security Certification_In-Memory Certification
In practice, there will not be only one user, and the password will be set by yourself. So we need to customize the user information. First, we create two users in memory, and Spring Security will match the username and password from the login page with the in-memory username and password for authentication.
-
// Security Configuration Class
-
@Configuration
-
public class SecurityConfig {
-
// Defining Authentication Logic
-
@Bean
-
public UserDetailsService userDetailsService(){
-
// 1. Authentication using in-memory data
-
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
-
// 2. Creating two users
-
UserDetails user1 = ("baizhan").password("123").authorities("admin").build();
-
UserDetails user2 = ("sxt").password("456").authorities("admin").build();
-
// 3. Add these two users to memory
-
(user1);
-
(user2);
-
return manager;
-
}
-
//Password encoder, does not parse passwords
-
@Bean
-
public PasswordEncoder passwordEncoder()
-
{
-
return ();
-
}
-
}
At this point in the authentication test, we can match the username and password passed from the login page with the in-memory username and password for authentication.
Spring Security Certification_UserDetailsService
In real projects, the authentication logic is subject to custom control. This willUserDetailsService You can customize the authentication logic by placing the implementation class of the interface into the Spring container.InMemoryUserDetailsManager just likeUserDetailsService interface, which matches the username and password passed from the login page with the in-memory username and password for authentication. Of course, we can also customize theUserDetailsService The implementation class of the interface.
-
public interface UserDetailsService {
-
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
-
}
UserDetailsService implementation class must override theloadUserByUsername method, which defines the specific authentication logic, with the parameterusername We need to query the user (usually from a database) based on the user name passed from the front-end and encapsulate the queried user into a UserDetails object, which is a user object provided by Spring Security and contains the user name, password, and permissions. Spring Security compares the password in the UserDetails object with the password provided by the client. Spring Security compares the password in the UserDetails object with the password provided by the client.
Spring Security Certification_Database Certification
Next we connect to the database for authentication:
1. Preparation of database data
CREATE TABLE `users` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(255), `password` varchar(255) , `phone` varchar(255) , PRIMARY KEY (`id`) ); INSERT INTO `users` VALUES (1, 'bazhn','bazhn', '13812345678'); INSERT INTO `users` VALUES (2, 'xt','xt', '13812345678');2. Writing user entity classes
@Data public class Users { private Integer id; private String username; private String password; private String phone; }3、Write dao interface
public interface UsersMapper extends BaseMapper<Users> {}
4. Add the @MapperScan annotation to the SpringBoot startup class to scan the Mapper folder.
@SpringBootApplication @MapperScan("") public class MysecurityApplication { public static void main(String[] args) { SpringApplication.run(, args); } }5, create UserDetailsService implementation class, write custom authentication logic
@Service public class MyUserDetailsService implements UserDetailsService { @Autowired private UsersMapper usersMapper; // Customized Authentication Logic @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { // 1. Constructing query conditions QueryWrapper<Users> wrapper = new QueryWrapper<Users>().eq("username",username); // 2. Querying Users Users users = (wrapper); // 3. Wrapping as a UserDetails object UserDetails userDetails = User .withUsername(()) .password(()) .authorities("admin") .build(); // 4. Returning the wrapped UserDetails object return userDetails; } }6. Test connection database authentication
Spring Securityaccreditation_PasswordEncoder
In actual development, for data security, the password is stored in the database not as the original password, but as an encrypted password. Instead, they are encrypted passwords. The parameters passed in by the user are plaintext passwords. In this case, you must use a password parser to compare the encrypted password with the plaintext password. The password parser in Spring Security is PasswordEncoder.
Spring Security requires a PasswordEncoder instance in the container, and the previously used
NoOpPasswordEncoder is an implementation of PasswordEncoder, which means that it doesn't parse passwords and uses plaintext passwords.
The official recommended password parser for Spring Security is BCryptPasswordEncoder. Let's learn how to use BCryptPasswordEncoder.
@SpringBootTest public class PasswordEncoderTest { @Test public void testBCryptPasswordEncoder(){ //Creating a parser PasswordEncoder encoder = new BCryptPasswordEncoder(); //password encryption String password = ("baizhan"); ("Encrypted:"+password); //Password verification /** * parameters1:: Plaintext passwords * parameters2:: Encrypted passwords * Return value: whether the calibration is successful or not */ boolean result = ("baizhan","$2a$10$/MImcrpDO21HAP2amayhme8j2SM0YM50/WO8YBH.NC1hEGGSU9ByO"); (result); } }In development, we willBCryptPasswordEncoder instance into the Spring container, and encrypts the password and saves it to the database after the user registration is complete.
//Password encoder @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); }
Spring Security Certification_Custom Login Page
Although Spring Security provides us with a login page, in real projects, we tend to use our own login page, and Spring Security also supports user-defined login pages. Spring Security also supports user-defined login pages, which can be used as follows:
1、Write the login page
2, in the Spring Security configuration class to customize the login page
@Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter{ //Spring Security Configuration @Override protected void configure(HttpSecurity http) throws Exception { // Customized form login () .loginPage("/") //Customize the login page .usernameParameter("username")// User name entries in forms .passwordParameter("password")// Password entries in forms .loginProcessingUrl("/login") // The login path to which the form will be submitted, and the methods of UserDetailsService will be executed automatically after the submission. .successForwardUrl("/main")//Path to jump after successful login .failureForwardUrl("/fail");//Path to jump after failed login // Resources requiring certification ().antMatchers("/").permitAll() //Login page does not require authentication .anyRequest().authenticated(); //All remaining requests require authentication //Disable csrf protection ().disable(); } @Override public void configure(WebSecurity web) throws Exception { // Static resource release ().antMatchers("/css/**"); } }CSRF Protection: CSRF: Cross-site request forgery is an attack method that forges a user's request to visit a trusted site in order to make an illegal request for access. Spring Security has CSRF protection turned on by default to prevent CSRF attacks, which restricts most methods except GET requests. We need to break the CSRF protection in order to use Spring Security normally.
Solution 1: Turn off CSRF protection:
http.csrf().disable();
Solution 2: Break through the CSRF protection:
CSRF in order to ensure that it is not accessed by other third-party websites, it is required to carry a token with the parameter name _csrf value when accessing, the token is generated on the server side, and if the token carried by the server side matches with the token successfully, then it will be accessed normally.
<form class="form" action="/login" method="post"> <! -- Adding a token hidden field to a form --> <input type="hidden" th:value="${_csrf.token}" name="_csrf" th:if="${_csrf}"/> <input type="text" placeholder="Username" name="username"> <input type="password" placeholder="Password." name="password"> <button type="submit">log in</button> </form>
Spring Security Certification_Session Management
Once the user is authenticated, sometimes we need to get information about the user, such as a message at the top of the website saying: Welcome, XXX. Spring Security stores the user information in a session and provides session management, which we can access from theSecurityContext object to get information about the user. SecurityContext object is bound to the current thread.
Getting user information is written as follows:
@RestController public class MyController { // Get current login user name @RequestMapping("/users/username") public String getUsername(){ // 1. Getting Session Objects SecurityContext context = (); // 2. Getting Authentication Objects Authentication authentication = (); // 3. Getting login user information UserDetails userDetails = (UserDetails) (); return (); } }
Spring Security Authentication_Handling of Successful Authentication
After successful login, if you need to execute some custom code in addition to jumping to the page, such as: statistics of visits, push messages and other operations, you can customize the login success processor.
1、Customize the login success processor
public class MyLoginSuccessHandler implements AuthenticationSuccessHandler { @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { // Get information about the logged-in user. UserDetails userDetails = (UserDetails)(); ("Username:"+()); ("Some operations..."); // Redirect to home page ("/main"); } }2、Configure the login success processor
() // Login with Forms .loginPage("/") // Customize the login page .usernameParameter("username") // User name entries in forms .passwordParameter("password") // Password entries in forms .loginProcessingUrl("/login") // The login path to which the form will be submitted, and the methods of UserDetailsService will be executed automatically after the submission. //.successForwardUrl("/main") //Path to jump after successful login .successHandler(new MyLoginSuccessHandler()) //Login Success Processor .failureForwardUrl("/fail"); //Path to jump after failed login
Spring Security Authentication_Handling after Authentication Failure
If you need to execute some customized code in addition to jumping to a page after a login failure, such as counting the number of failures, logging, etc., you can customize the login failure handler.
1、Customize the login failure processor
public class MyLoginFailureHandler implements AuthenticationFailureHandler { @Override public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { ("Record failure log..."); ("/fail"); } }2、Configure the login failure processor
() // Login with Forms .loginPage("/") // Customize the login page .usernameParameter("username") // User name entries in forms .passwordParameter("password") // Password entries in forms .loginProcessingUrl("/login") // The login path, the form is submitted to this path, and the methods of UserDetailsService are automatically executed after the submission. //.successForwardUrl("/main") //Path to jump after successful login .successHandler(new MyLoginSuccessHandler()) //Login Success Processor //.failureForwardUrl("/fail") //Path to jump after failed login .failureHandler(new MyLoginFailureHandler()); //Login Failure Processor // Resources requiring certification () .antMatchers("/").permitAll() //Login page does not require authentication .antMatchers("/fail").permitAll() //Failure pages do not require authentication .anyRequest().authenticated(); //All remaining requests require authentication
Spring Security Authentication_Exit Login
Logging out of a login is typically done in a system. After logging out, Spring Security performs the following actions:
1. Clear the authentication status
2, destroy the HttpSession object
3. Jump to the login page
In Spring Security, logging out is written as follows:
1、Configure the path to log out and the path to jump to after logging out
// Exit Login Configuration () .logoutUrl("/logout") // Logout Path .logoutSuccessUrl("/") // Path to jump after logging out .clearAuthentication(true) //Clear the authentication status, the default istrue .invalidateHttpSession(true); // Destroy the HttpSession object, the default istrue2. Add the logout hyperlink in the webpage
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>main page</title> </head> <body> <h1>main page</h1> <a href="/logout">Log out</a> </body> </html>
Spring Security Certification_Exit Success Handler
We can also customize the exit success handler to clean up some data after the exit, as follows:
1. Customize the exit success processor
public class MyLogoutSuccessHandler implements LogoutSuccessHandler { @Override public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { ("Clearing some data..."); ("/"); } }2. Configure the exit success processor
// Exit Login Configuration () .logoutUrl("/logout") // Logout Path // .logoutSuccessUrl("/") // Path to jump after logging out .clearAuthentication(true) //Clear the authentication status, the default istrue .invalidateHttpSession(true) // Destroy the HttpSession object, the default istrue .logoutSuccessHandler(new MyLogoutSuccessHandler()); //Customizing the Exit Success Site processor
Spring Security Certification_Remember Me
In Spring Security, Remember Me is a feature that eliminates the need to log in again the next time you access the system. When you log in using the Remember Me feature, Spring Security generates a token, which is stored in the database and generates a new token called the "Remember Me" token.remember-me The cookie is saved to the client. After that, the client will automatically bring the token when accessing the project, and can complete the authentication without logging in.
1. Writing the "Remember Me" configuration class
@Configuration public class RememberMeConfig { @Autowired private DataSource dataSource; // Token Repository @Bean public PersistentTokenRepository getPersistentTokenRepository() { // Set up a data source for the token controller that comes with Spring Security. JdbcTokenRepositoryImpl jdbcTokenRepositoryImpl = new JdbcTokenRepositoryImpl(); jdbcTokenRepositoryImpl.setDataSource(dataSource); //Automatic table creation, required on first startup, commented out on second startup // (true); return jdbcTokenRepositoryImpl; } }2. Modify the Security configuration class
// Remember Me Configuration () .userDetailsService(userDetailsService)//Which object to hand off the login logic to .tokenRepository(repository) //persistence layer object .tokenValiditySeconds(30); //Saving time in seconds3. Add a "Remember me" checkbox on the login page.
<form class="form" action="/login" method="post"> <input type="text" placeholder="Username" name="username"> <input type="password" placeholder="Password." name="password"> <input type="checkbox" name="remember-me" value="true"/>Remember me.</br> <button type="submit">log in</button> </form>
Spring Security Authorization_RBAC
Authorization means that after authentication, the system gives the user certain privileges, and the user can only access certain resources in the system according to the privileges.RBACIt is a commonly used authorization method in the industry and has two interpretations:
Role-Based Access Control
Role-based access control, i.e. authorization by role. For example, in an enterprise management system, the subject role of the general manager can query enterprise operation reports. Logic for:
-
if(Subject.hasRole("General Manager Role")){
-
Query operation report
-
}
If the roles for querying the operation report of the enterprise change to the general manager and shareholders, then you need to modify the judgment logic code:
-
if(Subject.hasRole("General Manager Role") || Subject.hasRole("Shareholder Role")){
-
Query operation report
-
}
At this point, we can find that when we need to modify the permissions of a role, we need to modify the authorization related code, and the system scalability is poor.
Resource-Based Access Control
Resource-based access control, i.e., authorization by resource (or privilege). For example, in an enterprise management system, a user must have the permission to query reports in order to query enterprise operation reports. The logic is:
-
if(Subject.hasPermission("Permission to query reports")){
-
Query operation report
-
}
In this way, the authority identification for querying reports is already defined in the system design, and even if the roles required for querying reports are changed to general manager and shareholders, there is no need to modify the authorization code, so the system is highly scalable. This authorization method is more commonly used.
Spring Security Authorization_Permission_Table Design
The relationship between users and permissions is many-to-many, i.e., users have multiple permissions, and permissions belong to multiple users, so the table is built as follows:
In this way, you need to specify which privileges the user has, such as: Zhang San has the privilege to query salary, that is, add a data in the middle table of user privileges, respectively record Zhang San and query salary privilege ID. but the number of privileges in the system may be very large, if you add one by one to maintain the data is more cumbersome. Therefore, the usual practice is to add another role table:
User roles and role permissions are many-to-many relationships, i.e., a user has multiple roles and a role belongs to multiple users; a role has multiple permissions and a permission belongs to multiple roles. In this way, you need to specify which roles a user has and which permissions a role has.
For example, Zhang San has the role of general manager, and the general manager has the authority to query salary and reports, so Zhang San has the authority to query salary and reports. In this way, you only need to manage a few roles when managing users, and you only need to manage a few permissions when managing roles. Next, we create five tables:
CREATE TABLE `users` (`uid` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `phone` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, PRIMARY KEY (`uid`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; INSERT INTO `users` VALUES (1, 'baizhan','$2a$10$.xLENt4b vfDvv7DyS5AVPT.U6', '13812345678'); CREATE TABLE `role` ( `rid` int(11) NOT NULL AUTO_INCREMENT, `roleName` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `roleDesc` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, PRIMARY KEY (`rid`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; INSERT INTO `role` VALUES (1,'General Manager','Managing the whole company'); INSERT INTO `role` VALUES (2,'Shareholders','Participation in corporate decision-making'); INSERT INTO `role` VALUES (3,'Finance','Managing corporate assets'); CREATE TABLE `permission` ( `pid` int(11) NOT NULL AUTO_INCREMENT, `permissionName` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, PRIMARY KEY (`pid`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; INSERT INTO `permission` VALUES (1,'Query Reports', '/reportform/find'); INSERT INTO `permission` VALUES (2,'Check salary', '/salary/find'); INSERT INTO `permission` VALUES (3,'Enquiry Tax', '/tax/find'); CREATE TABLE `users_role` ( `uid` int(255) NOT NULL, `rid` int(11) NOT NULL, PRIMARY KEY (`uid`, `rid`) USING BTREE, INDEX `rid`(`rid`) USING BTREE, CONSTRAINT `users_role_ibfk_1` FOREIGN KEY(`uid`) REFERENCES `users` (`uid`) ON DELETE RESTRICT ON UPDATE RESTRICT, CONSTRAINT `users_role_ibfk_2` FOREIGN KEY(`rid`) REFERENCES `role` (`rid`) ON DELETE RESTRICT ON UPDATE RESTRICT ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; INSERT INTO `users_role` VALUES (1, 2); INSERT INTO `users_role` VALUES (1, 3); CREATE TABLE `role_permission` ( `rid` int(11) NOT NULL, `pid` int(11) NOT NULL, PRIMARY KEY (`rid`, `pid`) USING BTREE, INDEX `pid`(`pid`) USING BTREE, CONSTRAINT `role_permission_ibfk_1` FOREIGN KEY (`rid`) REFERENCES `role` (`rid`) ON DELETE RESTRICT ON UPDATE RESTRICT, CONSTRAINT `role_permission_ibfk_2` FOREIGN KEY (`pid`) REFERENCES `permission` (`pid`) ON DELETE RESTRICT ON UPDATE RESTRICT ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; INSERT INTO `role_permission` VALUES (1, 1); INSERT INTO `role_permission` VALUES (2, 1); INSERT INTO `role_permission` VALUES (1, 2); INSERT INTO `role_permission` VALUES (3, 2); INSERT INTO `role_permission` VALUES (1, 3); INSERT INTO `role_permission` VALUES (2, 3);
Spring Security Authorization_Writing Query Permission Methods
To perform authorization after authentication you need to look up the user's privileges based on the user id, which is written as follows:
1, write users, roles, permissions entity class
// Don't name it User to avoid confusion with the User provided by Spring Security. @Data public class Users { private Integer uid; private String username; private String password; private String phone; } // Roles @Data public class Role { private String rid; private String roleName; private String roleDesc; } // Permissions @Data public class Permission { private String pid; private String permissionName; private String url; }2, write UserMapper interface
// Permission query by user name List<Permission> findPermissionByUsername(String username);3, in the resources directory to write UsersMapper mapping file
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-////DTD Mapper3.0//EN" "/dtd/"> <mapper namespace=""> <select id="findPermissionByUsername" parameterType="string" resultType=""> SELECT DISTINCT ,, FROM users LEFT JOIN users_role on = users_role.uid LEFT JOIN role on users_role.rid = LEFT JOIN role_permission on = role_permission.rid LEFT JOIN permission on role_permission.pid = where username = #{username} </select> </mapper>4. Test Methods
@SpringBootTest public class UsersMapperTest { @Autowired private UsersMapper usersMapper; @Test public void testFindPermissionByUsername(){ List<Permission> baizhan = usersMapper.findPermissionByUsername("baizhan"); baizhan.forEach(System.out::println); } }5、Modify the authentication logic to authorize the user after successful authentication
// Customized Authentication Logic @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { // 1. Constructing query conditions QueryWrapper<Users> wrapper = new QueryWrapper<Users>().eq("username",username); // 2. Querying Users Users users = (wrapper); if (users == null){ return null; } // 3. Querying User Privileges List<Permission> permissions = (username); // 4. Converting a Custom Permission Collection to a Collection of Security's Permission Types List<GrantedAuthority> grantedAuthorities = new ArrayList<>(); for (Permission permission : permissions) { grantedAuthorities.add(new SimpleGrantedAuthority(())); } // 5. Wrapping as a UserDetails object UserDetails userDetails = (()) .password(()) .authorities(grantedAuthorities) .build(); // 6. Returning the wrapped UserDetails object return userDetails; }
Spring Security Authorization_Configuration Class Setting Access Control
After authorizing users, we can set up access control for resources in the system, i.e., what privileges can be granted to access what resources.
1, write the controller class, add controller method resources
@RestController public class MyController { @GetMapping("/reportform/find") public String findReportForm() { return "Query statement"; } @GetMapping("/salary/find") public String findSalary() { return "Enquire about wages"; } @GetMapping("/staff/find") public String findStaff() { return "Query Employee"; } }2. Modify the Security configuration class
// Permission Blocking Configuration http.authorizeRequests() .antMatchers("/").permitAll() // indicates that any privilege can be accessed .antMatchers("/reportform/find").hasAnyAuthority("/reportform/find") // Configure resources with the required permissions .antMatchers("/salary/find").hasAnyAuthority("/salary/find") .antMatchers("/staff/find").hasAnyAuthority("/staff/find") .anyRequest().authenticated(); //Indicates that any request requires authentication for access3, test access to resources, due to the lack of permission to be intercepted access will be thrown 403 exceptions
Spring Security Authorization_Custom Access Control Logic
If there are a lot of resources, it is inefficient to configure the permissions one by one. We can customize the access control logic, i.e., when accessing a resource, we can determine whether the user has the permission to access the URL of the resource.
1. Customize the access control logic
@Service public class MyAuthorizationService { // Customize the access control logic, return value is whether or not the resource can be accessed public boolean hasPermission(HttpServletRequest request,Authentication authentication){ // Get the logged in user in the session Object principal = (); if (principal instanceof UserDetails){ // Getting access to logged in users Collection<? extends GrantedAuthority> authorities = ((UserDetails)principal).getAuthorities(); // Get the URL path of the request String uri = (); // Wrapping URL paths as permission objects SimpleGrantedAuthority authority = new SimpleGrantedAuthority(uri); // Determine if the user's permission set contains the requested URL permission object return authorities.contains(authority); } return false; } }2. Use customized access control logic in the configuration file
// Permission Blocking Configuration () .antMatchers("/").permitAll() //Indicates that any privilege can access the // Customized access control logic is used for any request .anyRequest().access("@(request,authentication)" );
Spring Security Authorization_Annotation Setting Access Control
In addition to configuration classes, SpringSecurity provides a number of access control annotations. These annotations are not available by default and need to be enabled.
@Secured
This annotation is a role-based permission control that requires the permission name in UserDetails to start with theROLE_ Beginning.
1, in the configuration class to open the use of annotations
@SpringBootApplication @MapperScan("") @EnableGlobalMethodSecurity(securedEnabled=true) public class MysecurityApplication { public static void main(String[] args) { SpringApplication.run(, args); } }2. Add annotations to the controller methods
@Secured("ROLE_reportform") @GetMapping("/reportform/find") public String findReportForm() { return "Query statement"; }
@PreAuthorize
This annotation determines whether a user has privileges before the method is executed
1, in the configuration class to open the use of annotations
@SpringBootApplication @MapperScan("") @EnableGlobalMethodSecurity(prePostEnabled = true) public class MysecurityApplication { public static void main(String[] args) { SpringApplication.run(, args); } }2. Add annotations to the controller methods
@PreAuthorize("hasAnyAuthority('/reportform/find')") @GetMapping("/reportform/find") public String findReportForm() { return "Query statement"; }
Spring Security Authorization_Access Control on the Front End
SpringSecurity can control the display effect in some view technologies. For example, in Thymeleaf, some menus are displayed only if the logged in user has certain permissions.
1, in the pom to introduce Spring Security and Thymeleaf integration dependencies
<! --Spring Security integration with Thymeleaf--> <dependency> <groupId></groupId> <artifactId>thymeleaf-extras-springsecurity5</artifactId> </dependency>2. Use the Security tag in Thymeleaf to control what is displayed on the front-end
<!DOCTYPE html> <html xmlns:th="" xmlns:sec="/thymeleaf-extras-springsecurity5"> <head> <meta charset="UTF-8"> <title>main page</title> </head> <body> <h1>main page</h1> <ul> <li sec:authorize="hasAnyAuthority('/reportform/find')"> <a href="/reportform/find">Query Reports</a></li> <li sec:authorize="hasAnyAuthority('/salary/find')"> <a href="/salary/find">Check your salary</a></li> <li sec:authorize="hasAnyAuthority('/staff/find')"> <a href="/staff/find">Enquire Employee</a> </li> </ul> <a href="/logout">Log out</a> </body> </html>3, so that the face of different rights of users, the front-end can display different menus
Spring Security Authorization_403 Handling Scheme
When using Spring Security, you will often see 403 (no permission), so the page is very unfriendly, we can customize the 403 exception handling scheme:
1. Preparation of the page on insufficient permissions
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>insufficient authority</title> </head> <body> <h1>You do not have enough permissions, please contact an administrator!</h1> </body> </html>2、Write permission insufficient processing class
public class MyAccessDeniedHandler implements AccessDeniedHandler { @Override public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { ("/"); } }3, configure exception handling in the Spring Security configuration file
//Exception handling http.exceptionHandling(). accessDeniedHandler(new MyAccessDeniedHandler());