Integrate Security Security Framework
Introduce dependencies
<dependency> <groupId></groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId></groupId> <artifactId>fastjson</artifactId> <version>1.2.79</version> </dependency>
Write configuration class WebSecurityConfig (custom resource permission rules processing)
package ; import ; import .*; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; /** * <p> * Security configuration class * </p> * * @author: Lei Zijie * @date:2022/8/6 */ @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private MyUserDetailsService myUserDetailsService; @Autowired private MyAuthenticationFailureHandler myAuthenticationFailureHandler; @Autowired private MyAuthenticationSuccessHandler myAuthenticationSuccessHandler; @Autowired private LogoutSuccessHandlerImpl logoutSuccessHandler; @Autowired private MyAuthenticationEntryPoint myAuthenticationEntryPoint; @Autowired private MyAccessDeniedHandler myAccessDeniedHandler; @Override public void configure(HttpSecurity http) throws Exception { // What is (cors pre-check request) It means that when you want to make a cross-domain request, you have to send a request in advance to see if the other person is blocking you or letting you go //Step 1: Solve cross-domain problems. Cors preflight request is released, let Spring security release all preflight requests (cors preflight requests) ().loginProcessingUrl("/login").permitAll(); ().requestMatchers(CorsUtils::isPreFlightRequest).permitAll(); //Release this iframe load ().frameOptions().disable(); ().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler); // //Disable csrf// ().disable(); // sessionManagement().sessionCreationPolicy() // .and().headers().cacheControl() //Configure permissions () // Release the registration request .antMatchers(,"/user/registerUser").permitAll() // Release swagger .antMatchers("/").permitAll() .anyRequest() .access(("@(authentication)")) .and().csrf().disable(); //Own filter (myUsernamePasswordAuthenticationFilter(), ); //Step 6: Handle exceptions: authentication failed and insufficient permissions ().authenticationEntryPoint(myAuthenticationEntryPoint).accessDeniedHandler(myAccessDeniedHandler); } //Leave the custom filter to factory management @Bean public MyUsernamePasswordAuthenticationFilter myUsernamePasswordAuthenticationFilter() throws Exception { MyUsernamePasswordAuthenticationFilter filter = new MyUsernamePasswordAuthenticationFilter(); (myAuthenticationSuccessHandler); (myAuthenticationFailureHandler); (authenticationManagerBean()); return filter; } @Bean public BCryptPasswordEncoder passwordEncoder(){ return new BCryptPasswordEncoder(); } //User password encryption verification @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { ( myUserDetailsService).passwordEncoder(passwordEncoder()); } }
Write a configuration custom interceptor (detached development)
- MyAuthenticationSuccessHandler (custom login successfully handled)
package ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; /** * <p> * Custom login successfully handled * </p> * * @author: Lei Zijie * @date:2022/8/6 */ @Component public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler { @Reference private UserLoginService userLoginService; @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { //Verification successfully comes to this processor // Then get user information UserAuth user = (UserAuth) (); ("application/json;charset=UTF-8"); ().write((() .setCode(ResultInfo.VERIFY_SUCCESS.getCode()) .setMessage(ResultInfo.VERIFY_SUCCESS.getMessage()).data("user", user))); //The following is a non-essential, this is a table used in my database to store login records //Update the user's login IP address, latest login time String ipAddress = (request); String ipSource = (ipAddress); User loginUser = (); UserLogin login = new UserLogin(); (()); (ipAddress); (ipSource); (()); (new Date()); //Check that the last login time is set to the last login time //This time should be set to redis. Redis will be stored as the last login time and will be updated every time. //Save the table (login); } }
- MyAuthenticationFailureHandler (custom login failure handling)
package ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; /** * <p> * Custom login failure handling * </p> * * @author: Lei Zijie * @date:2022/8/6 */ @Component public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler { @Override public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { //Come to the login failed processor //This return can be encapsulated just two. ("application/json;charset=UTF-8"); ().write((() .setCode(ResultInfo.LOGIN_FAILED.getCode()) .setMessage(ResultInfo.LOGIN_FAILED.getMessage()))); } }
- LogoutSuccessHandlerImpl (custom authentication cancellation processing)
package ; import ; import ; import ; import ; import ; import ; import ; import ; import ; /** * <p> * Custom authentication cancellation processing * </p> * * @author: Lei Zijie * @date:2022/8/6 */ @Component public class LogoutSuccessHandlerImpl implements LogoutSuccessHandler { @Override public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException { ("application/json;charset=UTF-8"); ().write((().setMessage("Log out successfully"))); } }
- Custom login account password processing
package ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; /** * <p> * Custom login account password processing * </p> * * @author: Lei Zijie * @date:2022/8/6 */ public class MyUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter { @Reference private UserService userService; @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { //If the json format is used, please apply/json; charset=UTF-8 //Front and backend separation Here is the json string that is received if (().equals(MediaType.APPLICATION_JSON_UTF8_VALUE) || ().equals(MediaType.APPLICATION_JSON_VALUE)){ ObjectMapper objectMapper = new ObjectMapper(); //Token object UsernamePasswordAuthenticationToken authRequest = null; //Take authenticationBean Map<String, String> authenticationBean = null; //Use try with resource to automatically release resources //Use try with resource to automatically release resources try (InputStream is = ()) { //To string to collection authenticationBean = (is, ); } catch (IOException e) { //Put the exception into the custom exception class (()); throw new MyAuthenticationException(()); } try { if (!()) { //Get account number and password String username = (SPRING_SECURITY_FORM_USERNAME_KEY); String password = (SPRING_SECURITY_FORM_PASSWORD_KEY); //Can verify the account number and password// ("username = " + username); // ("password = " + password); //Check whether the account number and password exist if ((username, password)) { //Insert the account and password into the UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password); setDetails(request, authRequest); return ().authenticate(authRequest); } } } catch (AuthenticationException e) { (); throw new MyAuthenticationException(()); } throw new MyAuthenticationException("User or password error"); } return (request,response); } }
- UserServiceImpl
@Component @Service @Slf4j @Transactional public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { @Autowired private UserMapper userMapper; @Autowired private BCryptPasswordEncoder bCryptPasswordEncoder; /** * Check whether the user account password exists * @param username Username * @param password * @return Does it exist */ @Override public boolean checkLogin(String username, String password) { //Finding the user from the user table, it gets the encrypted password QueryWrapper<User> wrapper = new QueryWrapper<>(); ("password").eq("username", username); User user = (wrapper); if(user==null){ return false; } //This is the encrypted password in the database String userPassword = (); //Match this with encryption and return true if it can match, but cannot return false if it can match. return (password, userPassword); } }
- Custom login processing
package ; import ; import ; import ; import ; import ; import ; import ; import ; import ; /** * <p> * Custom login processing * </p> * * @author: Lei Zijie * @date:2022/8/6 */ @Component public class MyAuthenticationEntryPoint implements AuthenticationEntryPoint { /** */ @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { ("application/json;charset=utf-8"); ().write( (().setMessage("Please log in"))); } }
- Custom permission processing
package ; import ; import ; import ; import ; import ; import ; import ; import ; import ; /** * <p> * Custom permission processing * </p> * * @author: Lei Zijie * @date:2022/8/6 */ @Component public class MyAccessDeniedHandler implements AccessDeniedHandler { @Override public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { ("application/json;charset=utf-8"); ().write((().setMessage("permission denied"))); } }
Custom authentication data sources
- Define the data source entity class in Security
package ; import ; import ; import ; import ; /** * <p> * Data source entity class in Security * </p> * * @author: Lei Zijie * @date:2022/8/6 */ public class UserAuth implements UserDetails { @Override public String toString() { return "UserAuth{" + "user=" + user + ", authorities=" + authorities + '}'; } private User user; private Collection<? extends GrantedAuthority> authorities; public UserAuth() { } public UserAuth(User user, Collection<? extends GrantedAuthority> authorities) { = user; = authorities; } public User getUser() { return user; } public void setUser(User user) { = user; } public void setAuthorities(Collection<? extends GrantedAuthority> authorities) { = authorities; } @Override public Collection<? extends GrantedAuthority> getAuthorities() { return authorities; } @Override public String getPassword() { return (); } @Override public String getUsername() { return (); } @Override public boolean isAccountNonExpired() { return true; } @Override public boolean isAccountNonLocked() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { return true; } }
- Customize data source configuration
package ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; /** * <p> * Customize data source configuration * </p> * * @author: Lei Zijie * @date:2022/8/6 */ @Service public class MyUserDetailsService implements UserDetailsService { @Reference private UserService userService; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { if(()){ throw new UsernameNotFoundException("Username is empty"); } //Look for user based on user name User user = (username); if(user!=null){ List<GrantedAuthority> authorities=new ArrayList<>(); //Finding user role list based on user name List<String> roles = (username); //This way, write to reduce object pointers. SimpleGrantedAuthority simpleGrantedAuthority=null; for (String role :roles){ simpleGrantedAuthority =new SimpleGrantedAuthority(role); (simpleGrantedAuthority); } UserAuth userAuth=new UserAuth(); (user); (authorities); return userAuth; } else { throw new UsernameNotFoundException("Nothing"); } } }
- UserServiceImpl
@Component @Service @Slf4j @Transactional public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { @Autowired private UserMapper userMapper; /** * Obtain user information through username * @param username Username * @return Queryed information */ @Override public User getUserByUsername(String username) { QueryWrapper<User> wrapper = new QueryWrapper<>(); ("username", username); User user = (wrapper); return user; } /** * Find permission information based on username * @param username Username * @return permission information collection */ @Override public List<String> listUserRolesByUsername(String username) { List<String> roles = (username); return roles; } }
- UserMapper.xml
!-- Find the user's permissions by username--> <select resultType=""> select tb_role.role_name from tb_role, tb_user, tb_role_user where tb_role.role_id=tb_role_user.role_id and tb_user.user_id=tb_role_user.user_id and tb_user.username=#{username} </select>
Custom exception handling
- MyaccessDeniedException
package ; import ; /** * <p> * * </p> * * @author: Lei Zijie * @date:2022/8/6 */ public class MyaccessDeniedException extends AccessDeniedException { public MyaccessDeniedException(String msg) { super(msg); } }
- MyAuthenticationException
package ; import ; /** * <p> * * </p> * * @author: Lei Zijie * @date:2022/8/6 */ public class MyAuthenticationException extends AuthenticationException { public MyAuthenticationException(String msg) { super(msg); } }
Permission judgment and acquisition (do not necessarily add)
package ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; /** * <p> * Permission judgment and acquisition * </p> * * @author: Lei Zijie * @date:2022/8/6 */ @Component public class DynamicPermission { private final static String PERMISSION_KEY="PERMISSION_KEY"; @Autowired private RedisUtil redisUtil; @Autowired HttpServletRequest request; @Reference private UserService userService; /** * Determine that you have access to the API * @param authentication * @return * @throws MyaccessDeniedException */ public boolean checkPermisstion(Authentication authentication) throws MyaccessDeniedException, IOException { String name = (); //If it is an anonymous user, give the anonymous user get permission to view if(("anonymousUser")){ String method = (); if(("GET")){ return true; }else{ throw new MyaccessDeniedException("Illegal operation!"); } } //Get the current user authentication information Object principal = (); if(principal instanceof UserDetails) { UserDetails userDetails = (UserDetails) principal; //Get the username to enter the username when logging in String username = (); //Get resource authentication through account to view the permission information table under the current user //This authentication is often used after querying. You can add it to the cache //lest List<Api> apiUrls = getApiUrlByUserName(username); //AntPathMatcher antPathMatcher = new AntPathMatcher(); //Current access path String requestURI = (); // Submission type String urlMethod = (); //Judge whether the current path is in the access resource boolean hashAntPath=false; int hasMethod=-1; AntPathMatcher pathMatcher = new AntPathMatcher(); //Judge whether the current access path is in the permission table for(Api item :apiUrls){ if(((), requestURI)){ hashAntPath=true; } hasMethod=().toUpperCase().indexOf(()); if(hashAntPath && hasMethod!=-1){ break; } } boolean res=hashAntPath && hasMethod!=-1; if(res){ return res; } else { throw new MyaccessDeniedException("User permissions are insufficient!"); } } else{ throw new MyaccessDeniedException("Not UserDetails type!"); } } private List<Api> getApiUrlByUserName(String username) { List<Api> urlApis=null; String key= PERMISSION_KEY+"_"+username; String api = (String) (key); //String api = (String) ().get(key); if(api!=null && api!="" ){ //urlApis= (api, ); // ("Cache"+urlApis); // return urlApis; urlApis= (api, ); (urlApis); return urlApis; } //Get the user's API permissions List<Api> apis = (username); //Add to cache and set the expiration time to half an hour (key,(apis),1800); //().set(key, (apis), (1800L)); return apis; } }
Summarize
The above is personal experience. I hope you can give you a reference and I hope you can support me more.