SpringBoot Integrates SpringSecurity Sample Implementation Separate Permission Annotation + JWT Logon Authentication

SpringSecurity is a security framework for Java enterprise applications, which mainly includes user authentication and user authorization. Compared to Shiro, Security is more powerful, it can easily expand to meet more security control requirements, but it also has a higher learning cost.Both frameworks have pros and cons. In actual development, it is important to decide which one to use based on business and project needs.

JWT is a specification for securely transferring information in Web applications. Essentially, it is the evolution of Token. It is a Token that generates encrypted user identity information. It is especially suitable for distributed single sign-on scenarios. Instead of saving user authentication information on the server side, it directly verifies Token to obtain user information, which makes single sign-on simpler and more flexible.

1. Project environment

  • SpringBoot version: 2.1.6

  • SpringSecurity Version: 5.1.5

  • MyBatis-Plus version: 3.1.0

  • JDK version: 1.8

  • Data table (SQL file in project): The passwords for test numbers in the database are encrypted, all of which are 123456


Maven relies on the following:

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--Security rely on -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <!-- MybatisPlus Core Library -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.1.0</version>
        </dependency>
        <!-- Introduce Ali Database Connection Pool -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.6</version>
        </dependency>
        <!-- StringUtilS tool -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.5</version>
        </dependency>
        <!-- JSON tool -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.45</version>
        </dependency>
        <!-- JWT rely on -->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-jwt</artifactId>
            <version>1.0.9.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.0</version>
        </dependency>
</dependencies>

The configuration is as follows:

# configure port
server:
  port: 8764
spring:
  # Configure Data Source
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/sans_security?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false
    username: root
    password: 123456
    type: com.alibaba.druid.pool.DruidDataSource
# JWT Configuration
jwt:
  # Key KEY
  secret: JWTSecret
  # HeaderKEY
  tokenHeader: Authorization
  # Token prefix character
  tokenPrefix: Sans-
  # Expiration time unit seconds 1 day after expiration=86400 7 days after expiration=604800
  expiration: 86400
  # Configure interfaces that do not require authentication
  antMatchers: /index,/login/**,/favicon.ico
# Mybatis-plus related configuration
mybatis-plus:
  # An XML scan, with multiple directories separated by commas or semicolons (telling Mapper the location of the corresponding XML file)
  mapper-locations: classpath:mapper/*.xml
  # The following configurations have default values and can be set without
  global-config:
    db-config:
      #Primary key type AUTO:'Database ID Self-Increasing'INPUT:'User Input ID', ID_WORKER:'Global Unique ID (Number Type Unique ID)', UUID:'Global Unique ID UUID';
      id-type: AUTO
      #Field Policy IGNORED: "Ignore Judgment" NOT_NULL: "Non-NULL Judgment") NOT_EMPTY: "Non-empty Judgment"
      field-strategy: NOT_EMPTY
      #Database type
      db-type: MYSQL
  configuration:
    # Whether to turn on Automatic Hump naming rule mapping: a similar mapping from database column names to Java attribute hump naming
    map-underscore-to-camel-case: true
    # When map is returned true: when the query data is empty the field is returned null,false: when the query data is not empty the field will be hidden
    call-setters-on-nulls: true
    # This configuration prints out the sql executed and can be used during development or testing
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

2. Write project base classes

Entity,Dao,Service, and other SpringSecurity users'Entity,Service classes are omitted here, see source code

Writing JWT tool classes

/**
 * JWT Tool class
 * @Author Sans
 * @CreateTime 2019/10/2 7:42
 */
@Slf4j
public class JWTTokenUtil {

    /**
     * Generate Token
     * @Author Sans
     * @CreateTime 2019/10/2 12:16
     * @Param  selfUserEntity User Security Entities
     * @Return Token
     */
    public static String createAccessToken(SelfUserEntity selfUserEntity){
        // Login successfully generated JWT
        String token = Jwts.builder()
                // Put in user name and user ID
                .setId(selfUserEntity.getUserId()+"")
                // theme
                .setSubject(selfUserEntity.getUsername())
                // Time filed
                .setIssuedAt(new Date())
                // Issuer
                .setIssuer("sans")
                // Custom Property Put in User Has Permissions
                .claim("authorities", JSON.toJSONString(selfUserEntity.getAuthorities()))
                // Failure Time
                .setExpiration(new Date(System.currentTimeMillis() + JWTConfig.expiration))
                // Signature algorithm and key
                .signWith(SignatureAlgorithm.HS512, JWTConfig.secret)
                .compact();
        return token;
    }
}

Write Temporarily Unprivileged Processing Class

/**
 * @Description No permission to process classes at this time
 * @Author Sans
 * @CreateTime 2019/10/3 8:39
 */
@Component
public class UserAuthAccessDeniedHandler implements AccessDeniedHandler{
    /**
     * No permission to return results at this time
     * @Author Sans
     * @CreateTime 2019/10/3 8:41
     */
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException exception){
        ResultUtil.responseJson(response,ResultUtil.resultCode(403,"Unauthorized"));
    }
}

Write user unregistered processing class

/**
 * User not logged in to processing class
 * @Author Sans
 * @CreateTime 2019/10/3 8:55
 */
@Component
public class UserAuthenticationEntryPointHandler implements AuthenticationEntryPoint {
    /**
     * User not logged in to return results
     * @Author Sans
     * @CreateTime 2019/10/3 9:01
     */
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception){
        ResultUtil.responseJson(response,ResultUtil.resultCode(401,"Not logged in"));
    }
}

Write Login Failure Handling Class

/**
 * @Description Logon Failure Handling Class
 * @Author Sans
 * @CreateTime 2019/10/3 9:06
 */
@Slf4j
@Component
public class UserLoginFailureHandler implements AuthenticationFailureHandler {
    /**
     * Logon failure returned results
     * @Author Sans
     * @CreateTime 2019/10/3 9:12
     */
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception){
        // These processing classes for operations can be handled differently depending on the exception
        if (exception instanceof UsernameNotFoundException){
            log.info("[Login Failure)"+exception.getMessage());
            ResultUtil.responseJson(response,ResultUtil.resultCode(500,"user name does not exist"));
        }
        if (exception instanceof LockedException){
            log.info("[Login Failure)"+exception.getMessage());
            ResultUtil.responseJson(response,ResultUtil.resultCode(500,"User frozen"));
        }
        if (exception instanceof BadCredentialsException){
            log.info("[Login Failure)"+exception.getMessage());
            ResultUtil.responseJson(response,ResultUtil.resultCode(500,"Incorrect username password"));
        }
        ResultUtil.responseJson(response,ResultUtil.resultCode(500,"Logon Failure"));
    }
}

Write Login Success Processing Class

/**
 * @Description Logon Success Processing Class
 * @Author Sans
 * @CreateTime 2019/10/3 9:13
 */
@Slf4j
@Component
public class UserLoginSuccessHandler implements AuthenticationSuccessHandler {
    /**
     * Logon successfully returned results
     * @Author Sans
     * @CreateTime 2019/10/3 9:27
     */
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication){
        // Assembling JWT
        SelfUserEntity selfUserEntity =  (SelfUserEntity) authentication.getPrincipal();
        String token = JWTTokenUtil.createAccessToken(selfUserEntity);
        token = JWTConfig.tokenPrefix + token;
        // Encapsulate Return Parameters
        Map<String,Object> resultData = new HashMap<>();
        resultData.put("code","200");
        resultData.put("msg", "Login Successful");
        resultData.put("token",token);
        ResultUtil.responseJson(response,resultData);
    }
}

Write Logout Success Processing Class

/**
 * User Logout Class
 * @Author Sans
 * @CreateTime 2019/10/3 9:42
 */
@Component
public class UserLogoutSuccessHandler implements LogoutSuccessHandler {
    /**
     * User logout returns results
     * Here the front end should clear the Token
     * @Author Sans
     * @CreateTime 2019/10/3 9:50
     */
    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication){
        Map<String,Object> resultData = new HashMap<>();
        resultData.put("code","200");
        resultData.put("msg", "Logout Success");
        SecurityContextHolder.clearContext();
        ResultUtil.responseJson(response,ResultUtil.resultSuccess(resultData));
    }
}

3. Write Security Core Classes

Write a custom login validation class

/**
 * Custom Logon Validation
 * @Author Sans
 * @CreateTime 2019/10/1 19:11
 */
@Component
public class UserAuthenticationProvider implements AuthenticationProvider {
    @Autowired
    private SelfUserDetailsService selfUserDetailsService;
    @Autowired
    private SysUserService sysUserService;
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        // Get the user name returned in the form input
        String userName = (String) authentication.getPrincipal();
        // Get the password entered in the form
        String password = (String) authentication.getCredentials();
        // Query whether the user exists
        SelfUserEntity userInfo = selfUserDetailsService.loadUserByUsername(userName);
        if (userInfo == null) {
            throw new UsernameNotFoundException("user name does not exist");
        }
        // We also want to determine if the password is correct, where our password is encrypted using BCryptPasswordEncoder
        if (!new BCryptPasswordEncoder().matches(password, userInfo.getPassword())) {
            throw new BadCredentialsException("Incorrect password");
        }
        // You can add some other information to your judgment, such as the user account has been deactivated.
        if (userInfo.getStatus().equals("PROHIBIT")){
            throw new LockedException("The user has been frozen");
        }
        // Collection of roles
        Set<GrantedAuthority> authorities = new HashSet<>();
        // Query User Roles
        List<SysRoleEntity> sysRoleEntityList = sysUserService.selectSysRoleByUserId(userInfo.getUserId());
        for (SysRoleEntity sysRoleEntity: sysRoleEntityList){
            authorities.add(new SimpleGrantedAuthority("ROLE_" + sysRoleEntity.getRoleName()));
        }
        userInfo.setAuthorities(authorities);
        // Log on
        return new UsernamePasswordAuthenticationToken(userInfo, password, authorities);
    }
    @Override
    public boolean supports(Class<?> authentication) {
        return true;
    }
}

Write custom PermissionEvaluator comment validation

/**
 * Custom permission comment validation
 * @Author Sans
 * @CreateTime 2019/10/6 13:31
 */
@Component
public class UserPermissionEvaluator implements PermissionEvaluator {
    @Autowired
    private SysUserService sysUserService;
    /**
     * hasPermission Authentication methods
     * Here you can just judge the permission expression in the PreAuthorize comment
     * In practice, databases can be designed to meet business needs for more sophisticated authentication through targetUrl and permission
     * @Author Sans
     * @CreateTime 2019/10/6 18:25
     * @Param  authentication  User Identity
     * @Param  targetUrl  Request Path
     * @Param  permission Request path permissions
     * @Return boolean Is Passed
     */
    @Override
    public boolean hasPermission(Authentication authentication, Object targetUrl, Object permission) {
        // Get user information
        SelfUserEntity selfUserEntity =(SelfUserEntity) authentication.getPrincipal();
        // Query user permissions (where permissions can be put into the cache to improve efficiency)
        Set<String> permissions = new HashSet<>();
        List<SysMenuEntity> sysMenuEntityList = sysUserService.selectSysMenuByUserId(selfUserEntity.getUserId());
        for (SysMenuEntity sysMenuEntity:sysMenuEntityList) {
            permissions.add(sysMenuEntity.getPermission());
        }
        // Permission comparison
        if (permissions.contains(permission.toString())){
            return true;
        }
        return false;
    }
    @Override
    public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
        return false;
    }
}

Write the SpringSecurity core configuration class

/**
 * SpringSecurity Core Configuration Class
 * @Author Sans
 * @CreateTime 2019/10/1 9:40
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true) //Open permission comment, off by default
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    /**
     * Custom Logon Success Processor
     */
    @Autowired
    private UserLoginSuccessHandler userLoginSuccessHandler;
    /**
     * Custom Logon Failure Processor
     */
    @Autowired
    private UserLoginFailureHandler userLoginFailureHandler;
    /**
     * Custom Logoff Success Processor
     */
    @Autowired
    private UserLogoutSuccessHandler userLogoutSuccessHandler;
    /**
     * Custom Temporary Permission Processor
     */
    @Autowired
    private UserAuthAccessDeniedHandler userAuthAccessDeniedHandler;
    /**
     * Customize Unlogged Processors
     */
    @Autowired
    private UserAuthenticationEntryPointHandler userAuthenticationEntryPointHandler;
    /**
     * Custom Login Verifier
     */
    @Autowired
    private UserAuthenticationProvider userAuthenticationProvider;

    /**
     * Encryption method
     * @Author Sans
     * @CreateTime 2019/10/1 14:00
     */
    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }
    /**
     * Inject custom PermissionEvaluator
     */
    @Bean
    public DefaultWebSecurityExpressionHandler userSecurityExpressionHandler(){
        DefaultWebSecurityExpressionHandler handler = new DefaultWebSecurityExpressionHandler();
        handler.setPermissionEvaluator(new UserPermissionEvaluator());
        return handler;
    }

    /**
     * Configure login validation logic
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth){
        //Here we can enable our own login validation logic
        auth.authenticationProvider(userAuthenticationProvider);
    }
    /**
     * Configuring control logic for security
     * @Author Sans
     * @CreateTime 2019/10/1 16:56
     * @Param  http request
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                //Requests or resources that do not validate permissions (read from configuration file)
               .antMatchers(JWTConfig.antMatchers.split(",")).permitAll()
                //Other needs to be logged in before they can be accessed
                .anyRequest().authenticated()
                .and()
                //Configure Unlogged Custom Processing Class
                .httpBasic().authenticationEntryPoint(userAuthenticationEntryPointHandler)
                .and()
                //Configure login address
                .formLogin()
                .loginProcessingUrl("/login/userLogin")
                //Configure Logon Success Custom Processing Class
                .successHandler(userLoginSuccessHandler)
                //Configure Login Failure Custom Handling Class
                .failureHandler(userLoginFailureHandler)
                .and()
                //Configure logout address
                .logout()
                .logoutUrl("/login/userLogout")
                //Configure User Logout Custom Processing Class
                .logoutSuccessHandler(userLogoutSuccessHandler)
                .and()
                //Configuration does not have permission to customize processing classes
                .exceptionHandling().accessDeniedHandler(userAuthAccessDeniedHandler)
                .and()
                // Open Cross Domain
                .cors()
                .and()
                // Cancel cross-station Request Forgery protection
                .csrf().disable();
        // No session required based on Token
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        // disable cache
        http.headers().cacheControl();
        // Add JWT filter
        http.addFilter(new JWTAuthenticationTokenFilter(authenticationManager()));
    }
}

4. Write JWT intercept classes

Write JWT Interface Request Check Interceptor

/**
 * JWT Interface Request Check Interceptor
 * When an interface is requested, it comes in here to verify that Token is legal and expired
 * @Author Sans
 * @CreateTime 2019/10/5 16:41
 */
@Slf4j
public class JWTAuthenticationTokenFilter extends BasicAuthenticationFilter {
    public JWTAuthenticationTokenFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        // Get Token for JWT in Request Header
        String tokenHeader = request.getHeader(JWTConfig.tokenHeader);
        if (null!=tokenHeader && tokenHeader.startsWith(JWTConfig.tokenPrefix)) {
            try {
                // Truncate JWT prefix
                String token = tokenHeader.replace(JWTConfig.tokenPrefix, "");
                // Parse JWT
                Claims claims = Jwts.parser()
                        .setSigningKey(JWTConfig.secret)
                        .parseClaimsJws(token)
                        .getBody();
                // Get User Name
                String username = claims.getSubject();
                String userId=claims.getId();
                if(!StringUtils.isEmpty(username)&&!StringUtils.isEmpty(userId)) {
                    // Get Roles
                    List<GrantedAuthority> authorities = new ArrayList<>();
                    String authority = claims.get("authorities").toString();
                    if(!StringUtils.isEmpty(authority)){
                        List<Map<String,String>> authorityMap = JSONObject.parseObject(authority, List.class);
                        for(Map<String,String> role : authorityMap){
                            if(!StringUtils.isEmpty(role)) {
                                authorities.add(new SimpleGrantedAuthority(role.get("authority")));
                            }
                        }
                    }
                    //Assembly parameters
                    SelfUserEntity selfUserEntity = new SelfUserEntity();
                    selfUserEntity.setUsername(claims.getSubject());
                    selfUserEntity.setUserId(Long.parseLong(claims.getId()));
                    selfUserEntity.setAuthorities(authorities);
                    UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(selfUserEntity, userId, authorities);
                    SecurityContextHolder.getContext().setAuthentication(authentication);
                }
            } catch (ExpiredJwtException e){
                log.info("Token Be overdue");
            } catch (Exception e) {
                log.info("Token invalid");
            }
        }
        filterChain.doFilter(request, response);
        return;
    }
}

5. Permission annotations and hasPermission permission extensions

Security allows us to use SpringEL expressions when defining the access permissions that URL methods should have to annotate. When defining the access permissions required, if the corresponding expression returns true, it means that we have the corresponding permissions. If not, it will go into the UserAuthAccessDeniedHandler that we have configured to handle. Here are some examples.Comments in the code have corresponding descriptions.

/**
     * Management side information
     * @Author Sans
     * @CreateTime 2019/10/2 14:22
     * @Return Map<String,Object> Return Data MAP
     */
    @PreAuthorize("hasRole('ADMIN')")
    @RequestMapping(value = "/info",method = RequestMethod.GET)
    public Map<String,Object> userLogin(){
        Map<String,Object> result = new HashMap<>();
        SelfUserEntity userDetails = SecurityUtil.getUserInfo();
        result.put("title","Management side information");
        result.put("data",userDetails);
        return ResultUtil.resultSuccess(result);
    }
    /**
     * Accessible with ADMIN or USER roles
     * @Author Sans
     * @CreateTime 2019/10/2 14:22
     * @Return Map<String,Object> Return Data MAP
     */
    @PreAuthorize("hasAnyRole('ADMIN','USER')")
    @RequestMapping(value = "/list",method = RequestMethod.GET)
    public Map<String,Object> list(){
        Map<String,Object> result = new HashMap<>();
        List<SysUserEntity> sysUserEntityList = sysUserService.list();
        result.put("title","Viewable with user or administrator roles");
        result.put("data",sysUserEntityList);
        return ResultUtil.resultSuccess(result);
    }
    /**
     * Accessible with ADMIN and USER roles
     * @Author Sans
     * @CreateTime 2019/10/2 14:22
     * @Return Map<String,Object> Return Data MAP
     */
    @PreAuthorize("hasRole('ADMIN') and hasRole('USER')")
    @RequestMapping(value = "/menuList",method = RequestMethod.GET)
    public Map<String,Object> menuList(){
        Map<String,Object> result = new HashMap<>();
        List<SysMenuEntity> sysMenuEntityList = sysMenuService.list();
        result.put("title","Viewable with user and administrator roles");
        result.put("data",sysMenuEntityList);
        return ResultUtil.resultSuccess(result);
    }

Usually hasRole and hasAnyRole can basically satisfy most authentication needs, but sometimes in more complex scenarios, these general representations fail to authenticate permissions, and Security also provides a solution for us.Extend the expression through hasPermission().Use hasPermission() to implement the PermissionEvaluator interface first.

/**
 * Custom permission comment validation
 * @Author Sans
 * @CreateTime 2019/10/6 13:31
 */
@Component
public class UserPermissionEvaluator implements PermissionEvaluator {
    @Autowired
    private SysUserService sysUserService;
    /**
     * hasPermission Authentication methods
     * Here you can just judge the permission expression in the PreAuthorize comment
     * In practice, databases can be designed to meet business needs for more sophisticated authentication through targetUrl and permission
     * Of course, targetUrl is not necessarily a URL that can be either a Data Id or an Administrator Identity, etc. It's designed to suit your needs
     * @Author Sans
     * @CreateTime 2019/10/6 18:25
     * @Param  authentication  User identity (Authentication parameter is automatically brought with it by default when using hasPermission expression)
     * @Param  targetUrl  Request Path
     * @Param  permission Request path permissions
     * @Return boolean Is Passed
     */
    @Override
    public boolean hasPermission(Authentication authentication, Object targetUrl, Object permission) {
        // Get user information
        SelfUserEntity selfUserEntity =(SelfUserEntity) authentication.getPrincipal();
        // Query user permissions (where permissions can be put into the cache to improve efficiency)
        Set<String> permissions = new HashSet<>();
        List<SysMenuEntity> sysMenuEntityList = sysUserService.selectSysMenuByUserId(selfUserEntity.getUserId());
        for (SysMenuEntity sysMenuEntity:sysMenuEntityList) {
            permissions.add(sysMenuEntity.getPermission());
        }
        // Permission comparison
        if (permissions.contains(permission.toString())){
            return true;
        }
        return false;
    }
    @Override
    public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
        return false;
    }
}

Add hasPermission example on request method

 /**
     * Accessible with sys:user:info permissions
     * hasPermission The first parameter is the request path The second parameter is the permission expression
     * @Author Sans
     * @CreateTime 2019/10/2 14:22
     * @Return Map<String,Object> Return Data MAP
     */
    @PreAuthorize("hasPermission('/admin/userList','sys:user:info')")
    @RequestMapping(value = "/userList",method = RequestMethod.GET)
    public Map<String,Object> userList(){
        Map<String,Object> result = new HashMap<>();
        List<SysUserEntity> sysUserEntityList = sysUserService.list();
        result.put("title","Have sys:user:info Permissions can be viewed");
        result.put("data",sysUserEntityList);
        return ResultUtil.resultSuccess(result);
    }

hasPermission can also be used in conjunction with other expressions

 /**
     * Accessible with ADMIN role and sys:role:info privileges
     * @Author Sans
     * @CreateTime 2019/10/2 14:22
     * @Return Map<String,Object> Return Data MAP
     */
    @PreAuthorize("hasRole('ADMIN') and hasPermission('/admin/adminRoleList','sys:role:info')")
    @RequestMapping(value = "/adminRoleList",method = RequestMethod.GET)
    public Map<String,Object> adminRoleList(){
        Map<String,Object> result = new HashMap<>();
        List<SysRoleEntity> sysRoleEntityList = sysRoleService.list();
        result.put("title","Have ADMIN Roles and sys:role:info Permissions are accessible");
        result.put("data",sysRoleEntityList);
        return ResultUtil.resultSuccess(result);
    }

6. Testing

Create Account User Encryption uses Security's recommended bCryptPasswordEncoder method

/**
     * Registered User
     */
    @Test
    public void contextLoads() {
        // Registered User
        SysUserEntity sysUserEntity = new SysUserEntity();
        sysUserEntity.setUsername("sans");
        sysUserEntity.setPassword(bCryptPasswordEncoder.encode("123456"));
        // Set User Status
        sysUserEntity.setStatus("NORMAL");
        sysUserService.save(sysUserEntity);
        // Assign Roles 1:ADMIN 2:USER
        SysUserRoleEntity sysUserRoleEntity = new SysUserRoleEntity();
        sysUserRoleEntity.setRoleId(2L);
        sysUserRoleEntity.setUserId(sysUserEntity.getUserId());
        sysUserRoleService.save(sysUserRoleEntity);
    }

Login to the USER role account and we will get an authenticated Token after successful login

Access the interface of the USER role, set the Token obtained in the previous step to Headers, Key is Authorization, and the JWTAuthenticationTokenFilter interceptor we previously implemented retrieves and parses Token based on Authorizationin the request header

Access to the ADMIN role's interface using the USER role Token is denied and told that it is not authorized (temporary unauthorized access will go into the UserAuthAccessDeniedHandler class we defined for processing)

Change the ADMIN role for login and access to the ADMIN interface

7. Project Source

189 original articles published. 6. 10,000 visits+
Private letter follow

Tags: MySQL Database Spring Mybatis

Posted on Sun, 15 Mar 2020 19:19:12 -0700 by BarmyArmy