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…