Integrate SpringSecurity in the rbac project

Integrate SpringSecurity in rbac project

prerequisite

Note: MvcJavaConfig, CheckLoginInterceptor, CheckPermissionInterceptor invalid

* Add dependencies

<!--spring security components-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

After adding dependencies, it was found that the verification code was intercepted. . .

* Add SecurityConfig configuration

SecurityConfig.java
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {<!-- -->

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private CorsFilter corsFilter;

    @Autowired
    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;


    @Override
    protected void configure(HttpSecurity http) throws Exception {<!-- -->
        http. authorizeRequests()
                // no authentication required
                .antMatchers("/api/login", "/api/code", "/api/logout")
                .permitAll()
                // All requests must be authenticated and must be accessed after logging in
                .anyRequest()
                .authenticated();
        // Not based on session, close csrf
        http.csrf().disable();
    }

Can complete the rbac project authentication function

* Log in (but no authentication)

* Authentication

LoginUser.java
@Data
public class LoginUser implements UserDetails {<!-- -->

    @Getter
    private Employee employee;

    public LoginUser(Employee employee) {<!-- -->
        this.employee = employee;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {<!-- -->
        return null;
    }

    @Override
    public String getPassword() {<!-- -->
        return employee. getPassword();
    }

    @Override
    public String getUsername() {<!-- -->
        return employee. getName();
    }

    /**
     * Whether the account has not expired, expired cannot be verified
     */
    @Override
    public boolean isAccountNonExpired() {<!-- -->
        return true;
    }

    /**
     * Specifies whether the user is unlocked, and locked users cannot be authenticated
     */
    @Override
    public boolean isAccountNonLocked() {<!-- -->
        return true;
    }


    /**
     * Whether the account has not expired, expired cannot be verified
     */
    @Override
    public boolean isCredentialsNonExpired() {<!-- -->
        return true;
    }

    /**
     * If available, disabled users cannot authenticate
     */
    @Override
    public boolean isEnabled() {<!-- -->
        return true;
    }
}
UserDetailsServiceImpl.java
@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private IEmployeeService employeeService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        Employee employee = employeeService. selectByUserName(username);
        Assert.notNull(employee,"Login user:" + username + "does not exist");
        // build UserDetails
        LoginUser loginUser = new LoginUser(employee);
        return loginUser;
    }
}
// Note: username is the username of the receiving browser
LoginServiceImpl.java
@Service
public class LoginServerImpl implements ILoginServer {<!-- -->

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private PermissionMapper permissionMapper;

    @Autowired
    private EmployeeMapper employeeMapper;


    @Autowired
    private AuthenticationManager authenticationManager;

    @Override
    public Map<String, String> VerificationCode() {<!-- -->
        // get verification code
        Map<String, String> verifyCode = VerifyCodeUtil.generateVerifyCode();
        // store in Redis
        String key = Constant.VerifyCode + verifyCode.get("uuid");
        String value = verifyCode. get("code");
        redisUtils.set(key,value,Constant.VERIFY_CODE_EXPIRES);
        // package verification code
        verifyCode. remove("code");
        return verifyCode;
    }

    @Override
    public Employee login(LoginInfoVo loginInfoVo) {<!-- -->
        // 1 check parameter
        Assert.notNull(loginInfoVo,"Illegal parameter");
        Assert.hasLength(loginInfoVo.getUsername(),"The length of the user name cannot be empty");
        Assert.hasLength(loginInfoVo.getPassword(),"The password length cannot be empty");
        // 2 verification verification code
            // Verification code sent by the user
        String userCode = loginInfoVo. getCode();
        String UserUuid = loginInfoVo. getUuid();
        Assert.notNull(userCode,"The verification code cannot be empty");
            // Get the verification code code from Redis
        String key = Constant. VerifyCode + UserUuid;
        String code = redisUtils. get(key);
            // Verify the verification code passed by the client
        Assert.state(VerifyCodeUtil.verification(userCode,code,true), "The verification code is incorrect");

// // 3 logins
// Employee employee = employeeMapper.login(loginInfoVo.getUsername(), loginInfoVo.getPassword());
// // 4 verify login logic
// Assert.notNull(employee,"The username or password is wrong");
        // ------springSecurity Authentication--------------------------

// try {<!-- -->
            UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(loginInfoVo.getUsername(), loginInfoVo.getPassword());
            Authentication authenticate = authenticationManager. authenticate(token);
            // If the authentication fails, an exception will be thrown
            // Run down normally, the code authentication is successful
            // TODO:
            // token.getPrincipal() ---> string:admin
            LoginUser loginUser = (LoginUser)authenticate.getPrincipal(); // loginUser
            Employee employee = loginUser. getEmployee();
// }catch (Exception e){<!-- -->
// e. printStackTrace();
// }

        // ------springSecurity Authentication--------------------------

        // Store user information in Redis
            // key design rbac:login_employee:emp_id
            // format of value storage json string
        String UserValue = JsonUtils.toJsonString(employee);
        String UserKey = Constant.LOGIN_EMPLOYEE_EMPID + employee.getId();
        redisUtils.set(UserKey,UserValue);

        // Store the permission information of the current user in Redis
        // Find the query employee_role through the id of the employee table to find the roleId, and then use the roleId to find the role_permission to the corresponding permissionId,
        // Query the corresponding permission table through permissionId to find the corresponding permission information
        List<String> selectExpressionByEmpId = permissionMapper.selectExpressionByEmpId(employee.getId());
        String PermissionValue = JsonUtils.toJsonString(selectExpressionByEmpId);
        String PermissionKey = Constant. LOGIN_PERMISSION_EMPID + employee. getId();
        redisUtils.set(PermissionKey,PermissionValue);

        return employee;
    }

    @Override
    public void logout(HttpServletRequest request) {<!-- -->
        // Get empId from the request header
        String userId = request. getHeader(Constant. LOGOUT_USER_ID);
        // parameter validation
        Assert.notNull(userId,"Illegal parameter");
        long employeeId = Long. parseLong(userId);

        // Clear the data in Redis
        redisUtils.del(Constant.LOGIN_PERMISSION_EMPID + employeeId); // permission
        redisUtils.del(Constant.LOGIN_EMPLOYEE_EMPID + employeeId); // user
    }


}
SecurityConfig.java
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {<!-- -->

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private CorsFilter corsFilter;

    @Autowired
    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;


    @Override
    protected void configure(HttpSecurity http) throws Exception {<!-- -->
        http. authorizeRequests()
                // no authentication required
                .antMatchers("/api/login", "/api/code", "/api/logout")
                .permitAll()
                // All requests must be authenticated and must be accessed after logging in
                .anyRequest()
                .authenticated();

        // add cross domain filter before authentication

        // add JWT filter
        http.addFilterBefore(jwtAuthenticationTokenFilter,
                UsernamePasswordAuthenticationFilter. class);
        // add CORS filter
        http.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class);

        // Not based on session, close csrf
        http.csrf().disable();
    }

    // authentication interface
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {<!-- -->
        // Write UserDetailsService, tell SS
        // and tell the cipher
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
        }

    /**
     * Solve the problem of not being able to inject AuthenticationManager directly
     * @return
     * @throws Exception
     */
    @Bean
    public AuthenticationManager authenticationManager() throws Exception {<!-- -->
        return super.authenticationManager(); // fetch directly from parent
    }

    @Bean
    public PasswordEncoder passwordEncoder(){<!-- -->
        return NoOpPasswordEncoder. getInstance();
    }


}

Phenomenon: You can log in at this time, but there are cross-domain problems and no authentication problems for each request

* Add cross domain filter

MvcJavaConfigV2.java
@Configuration
public class MvcJavaConfigV2 implements WebMvcConfigurer {<!-- -->
// cross-domain configuration
    @Bean
    public CorsFilter corsFilter(){<!-- -->
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowCredentials(true);
        // Set the access source address
        configuration.addAllowedOrigin("*");
        // Set the same-origin request header
        configuration.addAllowedHeader("*");
        // Set the same-origin request method
        configuration.addAllowedMethod("*");
        // valid for 1800s
        configuration.setMaxAge(1800L);
        // Add mapping path, intercept all requests
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**",configuration);
        // return new CorsFilter
        return new CorsFilter(source);
    }
}
JwtAuthenticationTokenFilter.java
/**
 * This filter should be added to SS
 * Every request must be authenticated, add a filter (JwtAuthenticationTokenFilter.java)
 */
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {<!-- -->
    @Autowired
    private RedisUtils redisUtils;
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {<!-- -->
        //
        String userId = request. getHeader(Constant. LOGOUT_USER_ID);
        String employeeJson = redisUtils.get(Constant.LOGIN_EMPLOYEE_EMPID + userId);
        if(!StringUtils.isEmpty(employeeJson)){<!-- -->
            // holder: bag
            Employee employee=(Employee) JsonUtils.fromJson(employeeJson, Employee.class);
            LoginUser loginUser = new LoginUser(employee);
            // Tell SS that I am authenticated
            UsernamePasswordAuthenticationToken token=
                    new UsernamePasswordAuthenticationToken(loginUser, loginUser. getPassword(), loginUser. getAuthorities());
            SecurityContextHolder.getContext().setAuthentication(token);
        }
        filterChain.doFilter(request, response);
    }
}
SecurityConfig.java
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {<!-- -->

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private CorsFilter corsFilter;

    @Autowired
    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;


    @Override
    protected void configure(HttpSecurity http) throws Exception {<!-- -->
        http. authorizeRequests()
                // no authentication required
                .antMatchers("/api/login", "/api/code", "/api/logout")
                .permitAll()
                // All requests must be authenticated and must be accessed after logging in
                .anyRequest()
                .authenticated();

        // add cross domain filter before authentication

        // Add JWT filter (each request must be authenticated, add a filter (JwtAuthenticationTokenFilter))
        http.addFilterBefore(jwtAuthenticationTokenFilter,
                UsernamePasswordAuthenticationFilter. class);
        // add CORS filter
        http.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class);

        // Not based on session, close csrf
        http.csrf().disable();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {<!-- -->
        // Write UserDetailsService, tell SS
        // and tell the cipher
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
        }

    /**
     * Solve the problem of not being able to inject AuthenticationManager directly
     * @return
     * @throws Exception
     */
    @Bean
    public AuthenticationManager authenticationManager() throws Exception {<!-- -->
        return super.authenticationManager(); // fetch directly from parent
    }

    @Bean
    public PasswordEncoder passwordEncoder(){<!-- -->
        return NoOpPasswordEncoder. getInstance();
    }


}

Phenomenon: Now you can log in and get authenticated…