SoFunction
Updated on 2025-04-14

Tutorial for springboot simple integration of security configuration

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&lt;String, String&gt; 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&lt;UserMapper, User&gt; 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&lt;User&gt; wrapper = new QueryWrapper&lt;&gt;();
        ("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&lt;? extends GrantedAuthority&gt; authorities;

    public UserAuth() {

    }

    public UserAuth(User user, Collection&lt;? extends GrantedAuthority&gt; authorities) {
         = user;
         = authorities;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
         = user;
    }

    public void setAuthorities(Collection&lt;? extends GrantedAuthority&gt; authorities) {
         = authorities;
    }

    @Override
    public Collection&lt;? extends GrantedAuthority&gt; 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&lt;GrantedAuthority&gt; authorities=new ArrayList&lt;&gt;();
            //Finding user role list based on user name            List&lt;String&gt; 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&lt;UserMapper, User&gt; implements UserService {
    @Autowired
    private UserMapper userMapper;
    
    
    /**
      * Obtain user information through username
      * @param username Username
      * @return Queryed information
      */
    @Override
    public User getUserByUsername(String username) {
        QueryWrapper&lt;User&gt; wrapper = new QueryWrapper&lt;&gt;();
        ("username", username);
        User user = (wrapper);
        return user;
    }
    
    /**
      * Find permission information based on username
      * @param username Username
      * @return permission information collection
      */
    @Override
    public List&lt;String&gt; listUserRolesByUsername(String username) {

        List&lt;String&gt; roles = (username);
        return roles;
    }
    
}
  • UserMapper.xml
      
!--    Find the user's permissions by username--&gt;
    &lt;select  resultType=""&gt;
        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}
    &lt;/select&gt;

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&lt;Api&gt; 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 &amp;&amp; hasMethod!=-1){
                    break;
                }
            }
            boolean res=hashAntPath &amp;&amp;  hasMethod!=-1;
            if(res){
                return  res;
            } else {
                throw  new MyaccessDeniedException("User permissions are insufficient!");
            }
        } else{
            throw  new MyaccessDeniedException("Not UserDetails type!");
        }
    }


    private List&lt;Api&gt;  getApiUrlByUserName(String username) {

        List&lt;Api&gt; urlApis=null;
        String key= PERMISSION_KEY+"_"+username;
        String api = (String) (key);
        //String api = (String) ().get(key);
        if(api!=null &amp;&amp; api!="" ){
            //urlApis= (api, );
            // ("Cache"+urlApis);            // return  urlApis;
            urlApis= (api, );
            (urlApis);
            return  urlApis;
        }
        
        //Get the user's API permissions        List&lt;Api&gt; 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.