web123456

Spring Security-Comprehensive Explanation (Learning Summary - From Beginning to Deepening)

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

  1. <!-- SpringMVC -->
  2. <dependency>
  3. <groupId></groupId>
  4. <artifactId>spring-boot-starter-web</artifactId>
  5. </dependency>
  6. <!--Thymeleaf-->
  7. <dependency>
  8. <groupId></groupId>
  9. <artifactId>spring-boot-starter-thymeleaf</artifactId>
  10. </dependency>
  11. <!--Spring Security-->
  12. <dependency>
  13. <groupId></groupId>
  14. <artifactId>spring-boot-starter-security</artifactId>
  15. </dependency>
  16. <! -- Mysql driver -->
  17. <dependency>
  18. <groupId>mysql</groupId>
  19. <artifactId>mysql-connector-java</artifactId>
  20. <scope>runtime</scope>
  21. </dependency>
  22. <!-- MyBatisPlus -->
  23. <dependency>
  24. <groupId></groupId>
  25. <artifactId>mybatis-plus-boot-starter</artifactId>
  26. <version>3.5.0</version>
  27. </dependency>
  28. <!-- lombok -->
  29. <dependency>
  30. <groupId></groupId>
  31. <artifactId>lombok</artifactId>
  32. <optional>true</optional>
  33. </dependency>
  34. <!-- junit -->
  35. <dependency>
  36. <groupId></groupId>
  37. <artifactId>spring-boot-starter-test</artifactId>
  38. <scope>test</scope>
  39. </dependency>

3, write configuration files for SpringBoot project

  1. server:
  2. port: 80
  3. # Log format
  4. logging:
  5. pattern:
  6. console: '%d{HH:mm:} %clr(%-5level) --- [%-15thread] %cyan(%-50logger{50}):%msg%n'
  7. # Data sources
  8. spring:
  9. datasource:
  10. driver-class-name:
  11. url: jdbc:mysql:///mysecurity?serverTimezone=UTC
  12. username: root
  13. password01: root

4, in the template folder to write the main page of the project

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>main page</title>
  6. </head>
  7. <body>
  8. <h1>main page</h1>
  9. </body>
  10. </html>

5. Writing access page controllers

  1. @Controller
  2. public class PageController {
  3. @RequestMapping("/{page}")
  4. public String showPage(@PathVariable String page){
  5. return page;
  6. }
  7. }

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.

  1. // Security Configuration Class
  2. @Configuration
  3. public class SecurityConfig {
  4. // Defining Authentication Logic
  5. @Bean
  6. public UserDetailsService userDetailsService(){
  7. // 1. Authentication using in-memory data
  8. InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
  9. // 2. Creating two users
  10. UserDetails user1 = ("baizhan").password("123").authorities("admin").build();
  11. UserDetails user2 = ("sxt").password("456").authorities("admin").build();
  12. // 3. Add these two users to memory
  13. (user1);
  14. (user2);
  15. return manager;
  16. }
  17. //Password encoder, does not parse passwords
  18. @Bean
  19. public PasswordEncoder passwordEncoder()
  20. {
  21. return ();
  22. }
  23. }

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.

  1. public interface UserDetailsService {
  2. UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
  3. }

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

  1. CREATE TABLE `users` (
  2. `id` int(11) NOT NULL AUTO_INCREMENT,
  3. `username` varchar(255),
  4. `password` varchar(255) ,
  5. `phone` varchar(255) ,
  6. PRIMARY KEY (`id`)
  7. );
  8. INSERT INTO `users` VALUES (1, 'bazhn','bazhn', '13812345678');
  9. INSERT INTO `users` VALUES (2, 'xt','xt', '13812345678');

2. Writing user entity classes

  1. @Data
  2. public class Users {
  3. private Integer id;
  4. private String username;
  5. private String password;
  6. private String phone;
  7. }

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.

  1. @SpringBootApplication
  2. @MapperScan("")
  3. public class MysecurityApplication {
  4. public static void main(String[] args)
  5. {
  6. SpringApplication.run(, args);
  7. }
  8. }

5, create UserDetailsService implementation class, write custom authentication logic

  1. @Service
  2. public class MyUserDetailsService
  3. implements UserDetailsService {
  4. @Autowired
  5. private UsersMapper usersMapper;
  6. // Customized Authentication Logic
  7. @Override
  8. public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
  9. // 1. Constructing query conditions
  10. QueryWrapper<Users> wrapper = new QueryWrapper<Users>().eq("username",username);
  11. // 2. Querying Users
  12. Users users = (wrapper);
  13. // 3. Wrapping as a UserDetails object
  14. UserDetails userDetails = User
  15. .withUsername(())
  16. .password(())
  17. .authorities("admin")
  18. .build();
  19. // 4. Returning the wrapped UserDetails object
  20. return userDetails;
  21. }
  22. }

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.

  1. @SpringBootTest
  2. public class PasswordEncoderTest {
  3. @Test
  4. public void testBCryptPasswordEncoder(){
  5. //Creating a parser
  6. PasswordEncoder encoder = new BCryptPasswordEncoder();
  7. //password encryption
  8. String password = ("baizhan");
  9. ("Encrypted:"+password);
  10. //Password verification
  11. /**
  12. * parameters1:: Plaintext passwords
  13. * parameters2:: Encrypted passwords
  14. * Return value: whether the calibration is successful or not
  15. */
  16. boolean result = ("baizhan","$2a$10$/MImcrpDO21HAP2amayhme8j2SM0YM50/WO8YBH.NC1hEGGSU9ByO");
  17. (result);
  18. }
  19. }

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.

  1. //Password encoder
  2. @Bean
  3. public PasswordEncoder passwordEncoder() {
  4. return new BCryptPasswordEncoder();
  5. }

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

  1. @Configuration
  2. public class SecurityConfig extends WebSecurityConfigurerAdapter{
  3. //Spring Security Configuration
  4. @Override
  5. protected void configure(HttpSecurity http) throws Exception {
  6. // Customized form login
  7. ()
  8. .loginPage("/") //Customize the login page
  9. .usernameParameter("username")// User name entries in forms
  10. .passwordParameter("password")// Password entries in forms
  11. .loginProcessingUrl("/login")
  12. // The login path to which the form will be submitted, and the methods of UserDetailsService will be executed automatically after the submission.
  13. .successForwardUrl("/main")//Path to jump after successful login
  14. .failureForwardUrl("/fail");//Path to jump after failed login
  15. // Resources requiring certification
  16. ().antMatchers("/").permitAll()
  17. //Login page does not require authentication
  18. .anyRequest().authenticated();
  19. //All remaining requests require authentication
  20. //Disable csrf protection
  21. ().disable();
  22. }
  23. @Override
  24. public void configure(WebSecurity web) throws Exception {
  25. // Static resource release
  26. ().antMatchers("/css/**");
  27. }
  28. }

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.

  1. <form class="form" action="/login" method="post">
  2. <! -- Adding a token hidden field to a form -->
  3. <input type="hidden" th:value="${_csrf.token}" name="_csrf" th:if="${_csrf}"/>
  4. <input type="text" placeholder="Username" name="username">
  5. <input type="password" placeholder="Password." name="password">
  6. <button type="submit">log in</button>
  7. </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:

  1. @RestController
  2. public class MyController {
  3. // Get current login user name
  4. @RequestMapping("/users/username")
  5. public String getUsername(){
  6. // 1. Getting Session Objects
  7. SecurityContext context = ();
  8. // 2. Getting Authentication Objects
  9. Authentication authentication = ();
  10. // 3. Getting login user information
  11. UserDetails userDetails = (UserDetails) ();
  12. return ();
  13. }
  14. }

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

  1. public class MyLoginSuccessHandler implements AuthenticationSuccessHandler {
  2. @Override
  3. public void onAuthenticationSuccess(HttpServletRequest
  4. request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
  5. // Get information about the logged-in user.
  6. UserDetails userDetails = (UserDetails)();
  7. ("Username:"+());
  8. ("Some operations...");
  9. // Redirect to home page
  10. ("/main");
  11. }
  12. }

2、Configure the login success processor

  1. () // Login with Forms
  2. .loginPage("/") // Customize the login page
  3. .usernameParameter("username") // User name entries in forms
  4. .passwordParameter("password") // Password entries in forms
  5. .loginProcessingUrl("/login") // The login path to which the form will be submitted, and the methods of UserDetailsService will be executed automatically after the submission.
  6. //.successForwardUrl("/main") //Path to jump after successful login
  7. .successHandler(new MyLoginSuccessHandler()) //Login Success Processor
  8. .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

  1. public class MyLoginFailureHandler implements AuthenticationFailureHandler {
  2. @Override
  3. public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
  4. AuthenticationException exception) throws IOException, ServletException {
  5. ("Record failure log...");
  6. ("/fail");
  7. }
  8. }

2、Configure the login failure processor

  1. () // Login with Forms
  2. .loginPage("/") // Customize the login page
  3. .usernameParameter("username") // User name entries in forms
  4. .passwordParameter("password") // Password entries in forms
  5. .loginProcessingUrl("/login") // The login path, the form is submitted to this path, and the methods of UserDetailsService are automatically executed after the submission.
  6. //.successForwardUrl("/main") //Path to jump after successful login
  7. .successHandler(new MyLoginSuccessHandler()) //Login Success Processor
  8. //.failureForwardUrl("/fail") //Path to jump after failed login
  9. .failureHandler(new MyLoginFailureHandler()); //Login Failure Processor
  10. // Resources requiring certification
  11. ()
  12. .antMatchers("/").permitAll() //Login page does not require authentication
  13. .antMatchers("/fail").permitAll() //Failure pages do not require authentication
  14. .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

  1. // Exit Login Configuration
  2. ()
  3. .logoutUrl("/logout") // Logout Path
  4. .logoutSuccessUrl("/") // Path to jump after logging out
  5. .clearAuthentication(true) //Clear the authentication status, the default istrue
  6. .invalidateHttpSession(true); // Destroy the HttpSession object, the default istrue

2. Add the logout hyperlink in the webpage

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>main page</title>
  6. </head>
  7. <body>
  8. <h1>main page</h1>
  9. <a href="/logout">Log out</a>
  10. </body>
  11. </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

  1. public class MyLogoutSuccessHandler implements LogoutSuccessHandler {
  2. @Override
  3. public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
  4. Authentication authentication) throws IOException, ServletException {
  5. ("Clearing some data...");
  6. ("/");
  7. }
  8. }

2. Configure the exit success processor

  1. // Exit Login Configuration
  2. ()
  3. .logoutUrl("/logout") // Logout Path
  4. // .logoutSuccessUrl("/") // Path to jump after logging out
  5. .clearAuthentication(true) //Clear the authentication status, the default istrue
  6. .invalidateHttpSession(true) // Destroy the HttpSession object, the default istrue
  7. .logoutSuccessHandler(new MyLogoutSuccessHandler()); //Customizing the Exit Success Site
  8. 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

  1. @Configuration
  2. public class RememberMeConfig {
  3. @Autowired
  4. private DataSource dataSource;
  5. // Token Repository
  6. @Bean
  7. public PersistentTokenRepository getPersistentTokenRepository() {
  8. // Set up a data source for the token controller that comes with Spring Security.
  9. JdbcTokenRepositoryImpl jdbcTokenRepositoryImpl = new JdbcTokenRepositoryImpl();
  10. jdbcTokenRepositoryImpl.setDataSource(dataSource);
  11. //Automatic table creation, required on first startup, commented out on second startup
  12. // (true);
  13. return jdbcTokenRepositoryImpl;
  14. }
  15. }

2. Modify the Security configuration class

  1. // Remember Me Configuration
  2. ()
  3. .userDetailsService(userDetailsService)//Which object to hand off the login logic to
  4. .tokenRepository(repository) //persistence layer object
  5. .tokenValiditySeconds(30); //Saving time in seconds

3. Add a "Remember me" checkbox on the login page.

  1. <form class="form" action="/login" method="post">
  2. <input type="text" placeholder="Username" name="username">
  3. <input type="password" placeholder="Password." name="password">
  4. <input type="checkbox" name="remember-me" value="true"/>Remember me.</br>
  5. <button type="submit">log in</button>
  6. </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:

  1. if(Subject.hasRole("General Manager Role")){
  2. Query operation report
  3. }

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:

  1. if(Subject.hasRole("General Manager Role") || Subject.hasRole("Shareholder Role")){
  2. Query operation report
  3. }

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:

  1. if(Subject.hasPermission("Permission to query reports")){
  2. Query operation report
  3. }

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:

  1. CREATE TABLE `users` (`uid` int(11) NOT NULL AUTO_INCREMENT,
  2. `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  3. `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  4. `phone` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  5. PRIMARY KEY (`uid`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 3
  6. CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
  7. INSERT INTO `users` VALUES (1, 'baizhan','$2a$10$.xLENt4b
  8. vfDvv7DyS5AVPT.U6', '13812345678');
  9. CREATE TABLE `role` (
  10. `rid` int(11) NOT NULL AUTO_INCREMENT,
  11. `roleName` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  12. `roleDesc` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  13. PRIMARY KEY (`rid`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 4
  14. CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
  15. INSERT INTO `role` VALUES (1,'General Manager','Managing the whole company');
  16. INSERT INTO `role` VALUES (2,'Shareholders','Participation in corporate decision-making');
  17. INSERT INTO `role` VALUES (3,'Finance','Managing corporate assets');
  18. CREATE TABLE `permission` (
  19. `pid` int(11) NOT NULL AUTO_INCREMENT,
  20. `permissionName` varchar(255) CHARACTER
  21. SET utf8 COLLATE utf8_general_ci NULL
  22. DEFAULT NULL,
  23. `url` varchar(255) CHARACTER SET utf8
  24. COLLATE utf8_general_ci NULL DEFAULT NULL,
  25. PRIMARY KEY (`pid`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 4
  26. CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
  27. INSERT INTO `permission` VALUES (1,'Query Reports', '/reportform/find');
  28. INSERT INTO `permission` VALUES (2,'Check salary', '/salary/find');
  29. INSERT INTO `permission` VALUES (3,'Enquiry Tax', '/tax/find');
  30. CREATE TABLE `users_role` (
  31. `uid` int(255) NOT NULL,
  32. `rid` int(11) NOT NULL,
  33. PRIMARY KEY (`uid`, `rid`) USING BTREE,
  34. INDEX `rid`(`rid`) USING BTREE,
  35. CONSTRAINT `users_role_ibfk_1` FOREIGN KEY(`uid`) REFERENCES `users` (`uid`) ON DELETE
  36. RESTRICT ON UPDATE RESTRICT,
  37. CONSTRAINT `users_role_ibfk_2` FOREIGN KEY(`rid`) REFERENCES `role` (`rid`) ON DELETE
  38. RESTRICT ON UPDATE RESTRICT ) ENGINE = InnoDB CHARACTER SET = utf8
  39. COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
  40. INSERT INTO `users_role` VALUES (1, 2);
  41. INSERT INTO `users_role` VALUES (1, 3);
  42. CREATE TABLE `role_permission` (
  43. `rid` int(11) NOT NULL,
  44. `pid` int(11) NOT NULL,
  45. PRIMARY KEY (`rid`, `pid`) USING BTREE,
  46. INDEX `pid`(`pid`) USING BTREE,
  47. CONSTRAINT `role_permission_ibfk_1` FOREIGN KEY (`rid`) REFERENCES `role`
  48. (`rid`) ON DELETE RESTRICT ON UPDATE
  49. RESTRICT,
  50. CONSTRAINT `role_permission_ibfk_2`
  51. FOREIGN KEY (`pid`) REFERENCES `permission`
  52. (`pid`) ON DELETE RESTRICT ON UPDATE
  53. RESTRICT
  54. ) ENGINE = InnoDB CHARACTER SET = utf8
  55. COLLATE = utf8_general_ci ROW_FORMAT =
  56. Dynamic;
  57. INSERT INTO `role_permission` VALUES (1, 1);
  58. INSERT INTO `role_permission` VALUES (2, 1);
  59. INSERT INTO `role_permission` VALUES (1, 2);
  60. INSERT INTO `role_permission` VALUES (3, 2);
  61. INSERT INTO `role_permission` VALUES (1, 3);
  62. 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

  1. // Don't name it User to avoid confusion with the User provided by Spring Security.
  2. @Data
  3. public class Users {
  4. private Integer uid;
  5. private String username;
  6. private String password;
  7. private String phone;
  8. }
  9. // Roles
  10. @Data
  11. public class Role {
  12. private String rid;
  13. private String roleName;
  14. private String roleDesc;
  15. }
  16. // Permissions
  17. @Data
  18. public class Permission {
  19. private String pid;
  20. private String permissionName;
  21. private String url;
  22. }

2, write UserMapper interface

  1. // Permission query by user name
  2. List<Permission> findPermissionByUsername(String username);

3, in the resources directory to write UsersMapper mapping file

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-////DTD Mapper3.0//EN"
  4. "/dtd/">
  5. <mapper namespace="">
  6. <select id="findPermissionByUsername" parameterType="string" resultType="">
  7. SELECT DISTINCT ,, FROM
  8. users
  9. LEFT JOIN users_role on = users_role.uid
  10. LEFT JOIN role on users_role.rid =
  11. LEFT JOIN role_permission on = role_permission.rid
  12. LEFT JOIN permission on role_permission.pid =
  13. where username = #{username}
  14. </select>
  15. </mapper>

4. Test Methods

  1. @SpringBootTest
  2. public class UsersMapperTest {
  3. @Autowired
  4. private UsersMapper usersMapper;
  5. @Test
  6. public void testFindPermissionByUsername(){
  7. List<Permission> baizhan = usersMapper.findPermissionByUsername("baizhan");
  8. baizhan.forEach(System.out::println);
  9. }
  10. }

5、Modify the authentication logic to authorize the user after successful authentication

  1. // Customized Authentication Logic
  2. @Override
  3. public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
  4. // 1. Constructing query conditions
  5. QueryWrapper<Users> wrapper = new QueryWrapper<Users>().eq("username",username);
  6. // 2. Querying Users
  7. Users users = (wrapper);
  8. if (users == null){
  9. return null;
  10. }
  11. // 3. Querying User Privileges
  12. List<Permission> permissions = (username);
  13. // 4. Converting a Custom Permission Collection to a Collection of Security's Permission Types
  14. List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
  15. for (Permission permission : permissions) {
  16. grantedAuthorities.add(new SimpleGrantedAuthority(()));
  17. }
  18. // 5. Wrapping as a UserDetails object
  19. UserDetails userDetails = (())
  20. .password(())
  21. .authorities(grantedAuthorities)
  22. .build();
  23. // 6. Returning the wrapped UserDetails object
  24. return userDetails;
  25. }

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

  1. @RestController
  2. public class MyController {
  3. @GetMapping("/reportform/find")
  4. public String findReportForm() {
  5. return "Query statement";
  6. }
  7. @GetMapping("/salary/find")
  8. public String findSalary() {
  9. return "Enquire about wages";
  10. }
  11. @GetMapping("/staff/find")
  12. public String findStaff() {
  13. return "Query Employee";
  14. }
  15. }

2. Modify the Security configuration class

  1. // Permission Blocking Configuration
  2. http.authorizeRequests()
  3. .antMatchers("/").permitAll() // indicates that any privilege can be accessed
  4. .antMatchers("/reportform/find").hasAnyAuthority("/reportform/find") // Configure resources with the required permissions
  5. .antMatchers("/salary/find").hasAnyAuthority("/salary/find")
  6. .antMatchers("/staff/find").hasAnyAuthority("/staff/find")
  7. .anyRequest().authenticated(); //Indicates that any request requires authentication for access

3, 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

  1. @Service
  2. public class MyAuthorizationService {
  3. // Customize the access control logic, return value is whether or not the resource can be accessed
  4. public boolean hasPermission(HttpServletRequest request,Authentication authentication){
  5. // Get the logged in user in the session
  6. Object principal = ();
  7. if (principal instanceof UserDetails){
  8. // Getting access to logged in users
  9. Collection<? extends GrantedAuthority> authorities = ((UserDetails)principal).getAuthorities();
  10. // Get the URL path of the request
  11. String uri = ();
  12. // Wrapping URL paths as permission objects
  13. SimpleGrantedAuthority authority = new SimpleGrantedAuthority(uri);
  14. // Determine if the user's permission set contains the requested URL permission object
  15. return authorities.contains(authority);
  16. }
  17. return false;
  18. }
  19. }

2. Use customized access control logic in the configuration file

  1. // Permission Blocking Configuration
  2. ()
  3. .antMatchers("/").permitAll() //Indicates that any privilege can access the
  4. // Customized access control logic is used for any request
  5. .anyRequest().access("@(request,authentication)"
  6. );

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

  1. @SpringBootApplication
  2. @MapperScan("")
  3. @EnableGlobalMethodSecurity(securedEnabled=true)
  4. public class MysecurityApplication {
  5. public static void main(String[] args)
  6. {
  7. SpringApplication.run(, args);
  8. }
  9. }

2. Add annotations to the controller methods

  1. @Secured("ROLE_reportform")
  2. @GetMapping("/reportform/find")
  3. public String findReportForm() {
  4. return "Query statement";
  5. }

@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

  1. @SpringBootApplication
  2. @MapperScan("")
  3. @EnableGlobalMethodSecurity(prePostEnabled = true)
  4. public class MysecurityApplication {
  5. public static void main(String[] args)
  6. {
  7. SpringApplication.run(, args);
  8. }
  9. }

2. Add annotations to the controller methods

  1. @PreAuthorize("hasAnyAuthority('/reportform/find')")
  2. @GetMapping("/reportform/find")
  3. public String findReportForm() {
  4. return "Query statement";
  5. }

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

  1. <! --Spring Security integration with Thymeleaf-->
  2. <dependency>
  3. <groupId></groupId>
  4. <artifactId>thymeleaf-extras-springsecurity5</artifactId>
  5. </dependency>

2. Use the Security tag in Thymeleaf to control what is displayed on the front-end

  1. <!DOCTYPE html>
  2. <html xmlns:th=""
  3. xmlns:sec="/thymeleaf-extras-springsecurity5">
  4. <head>
  5. <meta charset="UTF-8">
  6. <title>main page</title>
  7. </head>
  8. <body>
  9. <h1>main page</h1>
  10. <ul>
  11. <li sec:authorize="hasAnyAuthority('/reportform/find')">
  12. <a href="/reportform/find">Query Reports</a></li>
  13. <li sec:authorize="hasAnyAuthority('/salary/find')">
  14. <a href="/salary/find">Check your salary</a></li>
  15. <li sec:authorize="hasAnyAuthority('/staff/find')">
  16. <a href="/staff/find">Enquire Employee</a>
  17. </li>
  18. </ul>
  19. <a href="/logout">Log out</a>
  20. </body>
  21. </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

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>insufficient authority</title>
  6. </head>
  7. <body>
  8. <h1>You do not have enough permissions, please contact an administrator!</h1>
  9. </body>
  10. </html>

2、Write permission insufficient processing class

  1. public class MyAccessDeniedHandler implements AccessDeniedHandler {
  2. @Override
  3. public void handle(HttpServletRequest request, HttpServletResponse response,
  4. AccessDeniedException accessDeniedException) throws IOException, ServletException {
  5. ("/");
  6. }
  7. }

3, configure exception handling in the Spring Security configuration file

  1. //Exception handling
  2. http.exceptionHandling().
  3. accessDeniedHandler(new MyAccessDeniedHandler());