Java security framework

Time:2020-11-27

The article is mainly divided into three parts
1. The architecture and core components of spring security are as follows: (1) authentication; (2) authority interception; (3) database management; (4) authority caching; (5) custom decision making; and;
2. To build and use the environment, the current popular spring boot is used to build the environment, and the actual examples in the project are used to do several cases;
3. The advantages and disadvantages of spring security, combined with the implementation of several cases in the second part, summarizes the advantages and disadvantages of spring security.

1. Introduction to spring security

Overall introduction, spring security provides comprehensive security services for enterprise application software developed based on J2EE, especially for enterprise software projects developed with spring. If you are familiar with spring, especially the dependency injection principle of spring, it will help you master spring security more quickly. At present, spring is used There are many reasons for security. Usually, solutions for typical application scenarios cannot be found in J2EE servlet specification and EJB specification. When referring to these specifications, it is particularly important to point out that they cannot be migrated at war or ear level. If you need to change the server environment, you need to do a lot of work in the new target environment to reconfigure the security of your application, Spring security solves these problems and provides you with many useful customizable security features.
Spring security consists of three main components:SecurityContextAuthenticationManagerAccessDecisionManager.

Spring Security主要组件图
Figure 1-1 main components of spring security

1.1 certification

Spring security provides many filters, which intercept servlet requests, forward these requests to authentication processing filter and access decision filter for processing, and force security to authenticate user identity and user rights to achieve the purpose of protecting web resources. Spring security security mechanism includes two main operations,authenticationandverification, which can also be called permission control. This is spring The two main directions of security are authentication, which is the process of establishing a claimed principal for the user. This principal generally refers to the user’s equipment or other systems that can perform actions in the system. Authentication refers to whether the user can perform an operation in the application. Before the authorization judgment is reached, the identity principal has been established by the identity authentication process. Below are several common authentication modes. They are not detailed in this paper. The old fellow who needs detailed understanding can check the corresponding information by themselves.

  1. BasicHTTP1.0A challenge / response based authentication mode is proposed, which can be accessed only after user name and password authentication are provided for a specific realm, and the password is transmitted in plaintext. Disadvantages: ① stateless results in authentication information being carried in every communication, even for resources that have been authenticated; ② insufficient transmission security, authentication information is usedBase64Coding, which is basically plaintext transmission, is easy to intercept messages and steal authentication information.
  2. DigestHTTP1.1In order to solve the security problem of basic mode, it is used to replace the original basic authentication mode. Digest authentication also adopts challenge / response authentication mode, and the basic authentication process is similar. Digest mode avoids the password transmission in plaintext on the network and improves the security, but it still has some shortcomings, such as the authentication message is intercepted by the attacker, and the attacker can obtain the resources.
  3. X.509Certification: certificate,X.509It is a very general certificate format. The certificate includes version number, serial number (unique), signature, issuer, validity period, principal and principal public key.
  4. LDAP: Lightweight Directory Access Protocol.
  5. Form: form based authentication mode.

1.2 authority interception

image-20201024122405276
Figure 1-2 user request
Java security framework
Figure 1-3 filter

Spring security provides many filters, among whichSecurityContextPersistenceFilterUsernamePasswordAuthenticationFilterFilterSecurityInterceptorCorresponding separatelySecurityContextAuthenticationManagerAccessDecisionManagerThe treatment of.

Spring Security过滤链流程图
Figure 1-4 flow chart of spring security filter chain

The functions of each filter are described below.

filter describe
WebAsyncManagerIntegrationFilter set upSecurityContextTo an asynchronous thread to obtain user context information
SecurityContextPersistenceFilter Throughout the request processSecurityContextCreate and clean up
1. Not logged in,SecurityContextNull, create a newThreadLocalOfSecurityContextfillSecurityContextHolder.
2. Logged in fromSecurityContextRepositoryAcquiredSecurityContextObject
Both requests are cleared after completionSecurityContextHolder, and updateSecurityContextRepository
HeaderWriterFilter Add header information to response object
CsrfFilter Filter to prevent CSRF attack (Cross Site Request Forgery)
LogoutFilter Logout processing
UsernamePasswordAuthenticationFilter Get the user name and password of the form and process the login request based on the form
DefaultLoginPageGeneratingFilter Configure login page
BasicAuthenticationFilter Detect and process HTTP basic authentication and put the results intoSecurityContextHolder
RequestCacheAwareFilter Cache for processing request requests
SecurityContextHolderAwareRequestFilter Wrap request for easy accessSecurityContextHolder
AnonymousAuthenticationFilter When the filter is called, anonymous information does not exist
SessionManagementFilter When the user login authentication is detected, the corresponding session management is performed
ExceptionTranslationFilter handleAccessDeniedExceptionAccess exceptions andAuthenticationExceptionAuthentication exception
FilterSecurityInterceptor Detects whether the user has access to the resource path

1.3 database management

Spring Security核心处理流程
Figure 1-5 core processing flow of spring security

The above figure shows the core processing flow of spring security. When a user logs in, he / she will be authenticated first. If he / she fails to pass the authentication, he / she will be required to re authenticate. When the user ID card is passed, the role manager will be called to determine whether he / she can access. Here, if you want to manage users and permissions in database, you need to customize the user login function. Spring security has provided an interfaceUserDetailsService

package org.springframework.security.core.userdetails;

public interface UserDetailsService {
	
	/**
	 * Locates the user based on the username. In the actual implementation, the search
	 * may possibly be case sensitive, or case insensitive depending on how the
	 * implementation instance is configured. In this case, the UserDetails
	 * object that comes back may have a username that is of a different case than what
	 * was actually requested..
	 *
	 * @param username the username identifying the user whose data is required.
	 *
	 * @return a fully populated user record (never null)
	 *
	 * @throws UsernameNotFoundException if the user could not be found or the user has no
	 * GrantedAuthority
	 */
	UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
    
}

UserDetailServiceThe interface has only one method. From the method name, we can see that the method obtains the user information through the user name, but the return result isUserDetailsObject,UserDetailsIt is also an interface. If any method in the interface returns false, the user’s credentials will be considered invalid.

package org.springframework.security.core.userdetails;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;

import java.io.Serializable;
import java.util.Collection;

/**
 * Provides core user information.
 *
 * 
 * Implementations are not used directly by Spring Security for security purposes. They
 * simply store user information which is later encapsulated into {@link Authentication}
 * objects. This allows non-security related user information (such as email addresses,
 * telephone numbers etc) to be stored in a convenient location.
 * 
 * Concrete implementations must take particular care to ensure the non-null contract
 * detailed for each method is enforced. See
 * {@link org.springframework.security.core.userdetails.User} for a reference
 * implementation (which you might like to extend or use in your code).
 *
 * @see UserDetailsService
 * @see UserCache
 *
 * @author Ben Alex
 */
public interface UserDetails extends Serializable {
	// ~ Methods
	// ========================================================================================================

	/**
	 * Returns the authorities granted to the user. Cannot return null.
	 *
	 * @return the authorities, sorted by natural key (never null)
	 */
	Collection extends grantedauthority > getauthorities(); // permission collection

	/**
	 * Returns the password used to authenticate the user.
	 *
	 * @return the password
	 */
	String getpassword(); // password

	/**
	 * Returns the username used to authenticate the user. Cannot return null.
	 *
	 * @return the username (never null)
	 */
	String getusername(); // user name

	/**
	 * Indicates whether the user's account has expired. An expired account cannot be
	 * authenticated.
	 *
	 * @return true if the user's account is valid (ie non-expired),
	 * false if no longer valid (ie expired)
	 */
	Boolean isaccountnonexpired(); // is the account expired

	/**
	 * Indicates whether the user is locked or unlocked. A locked user cannot be
	 * authenticated.
	 *
	 * @return true if the user is not locked, false otherwise
	 */
	Boolean isaccountnonlocked(); // is the account locked

	/**
	 * Indicates whether the user's credentials (password) has expired. Expired
	 * credentials prevent authentication.
	 *
	 * @return true if the user's credentials are valid (ie non-expired),
	 * false if no longer valid (ie expired)
	 */
	Boolean iscredentialsnonexpired(); // is the certificate expired

	/**
	 * Indicates whether the user is enabled or disabled. A disabled user cannot be
	 * authenticated.
	 *
	 * @return true if the user is enabled, false otherwise
	 */
	Boolean isenabled(); // is the account valid
}

What needs to be noted here is thatAuthenticationAndUserDetailsObject differentiation,AuthenticationObject is the security object used by spring security to access and control user informationAuthenticationThe object has two states: UN authenticated and authenticated. When it is passed into the authentication manager as a parameter, it is an authenticated object. It obtains the user’s identity authentication information from the client, such as user name and password. It can be obtained from a login page or from a cookie, and the system automatically generates oneAuthenticationObject, and here’s theUserDetailsIt represents a source of user security information. This source can be returned from the database, LDAP server, and Ca center. What spring security needs to do is not authenticateAuthenticationObjects andUserDetailsObject. After successful matching, theUserDetailsThe permission information in the object is copied toAuthenticationTo form a completeAuthenticationObject to share with other components.

package org.springframework.security.core;

import java.io.Serializable;
import java.security.Principal;
import java.util.Collection;

import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.context.SecurityContextHolder;

public interface Authentication extends Principal, Serializable {

    /**Permission set*/
	Collection extends GrantedAuthority> getAuthorities();

	/**Get voucher*/
	Object getCredentials();

	/**Get some additional information about certification*/
	Object getDetails();

	/**Previously certified entities*/
	Object getPrincipal();

	/**Is it certified*/
	boolean isAuthenticated();

	/**
	 * See {@link #isAuthenticated()} for a full description.
	 * 
	 * Implementations should always allow this method to be called with a
	 * false parameter, as this is used by various classes to specify the
	 * authentication token should not be trusted. If an implementation wishes to reject
	 * an invocation with a true parameter (which would indicate the
	 * authentication token is trusted - a potential security risk) the implementation
	 * should throw an {@link IllegalArgumentException}.
	 *
	 * @param isAuthenticated true if the token should be trusted (which may
	 * result in an exception) or false if the token should not be trusted
	 *
	 * @throws IllegalArgumentException if an attempt to make the authentication token
	 * trusted (by passing true as the argument) is rejected due to the
	 * implementation being immutable or implementing its own alternative approach to
	 * {@link #isAuthenticated()}
	 */
	void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException;
}

After understanding the above three objects of spring security, we need to implement them manually when we need database management usersUserDetailsServiceObjectloadUserByUsernameMethod, we need to prepare the following data tables at the same time, which are user table, role table, permission table, user and role relationship table_ Role), permission and role relationship table (permission)_ role),UserDetailsThe user status in the user table is filled with the attributes in the user table,UserDetailsIn this way, user authentication and user permission set can be managed in the database.

1.4 permission cache

Spring security’s authority caching and database management are related to user authentication, so they are all related to user authenticationUserDetailsUnlike database management, spring security provides a cacheUserDetailsServiceThe implementation class of. The name of this class isCachingUserDetailsService

package org.springframework.security.authentication;

import org.springframework.security.core.userdetails.UserCache;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.cache.NullUserCache;
import org.springframework.util.Assert;

/**
 *
 * @author Luke Taylor
 * @since 2.0
 */
public class CachingUserDetailsService implements UserDetailsService {
	private UserCache userCache = new NullUserCache();
	private final UserDetailsService delegate;

	public CachingUserDetailsService(UserDetailsService delegate) {
		this.delegate = delegate;
	}

	public UserCache getUserCache() {
		return userCache;
	}

	public void setUserCache(UserCache userCache) {
		this.userCache = userCache;
	}

	public UserDetails loadUserByUsername(String username) {
		UserDetails user = userCache.getUserFromCache(username);
		//When there is no userdetails in the cache, it is loaded through the userdetailsservice
		if (user == null) {
			user = delegate.loadUserByUsername(username);
		}

		Assert.notNull(user, () -> "UserDetailsService " + delegate
				+ " returned null for username " + username + ". "
				+ "This is an interface contract violation");
		//Store the userdetails in the cache and return the userdetails
		userCache.putUserInCache(user);
		return user;
	}
}

CachingUserDetailsServiceClass receives aUserDetailsOfUserDetailsServiceImplementation class, when you need to loadUserDetailsIf there is noUserDetailsIf there is, then the heldUserDetailsServiceThe implementation class is loaded, and then the loaded results are stored in the cache,UserDetailsInteraction with the cache is done throughUserCacheInterface,CachingUserDetailsServiceBy default, you have oneUserCacheOfNullUserCache()realization. The cache provided by spring security is based on memory, and it is cachedUserDetailsObject, in practical applications, more cache is generally used, such as redis, and more data such as permission related information will be cached.

2.5 user defined decision

After the user authentication is passed, spring security will call a role manager to determine whether it can continue to access. In the [spring security core processing flow (Figure 1-5)] (ා 1.3 database management)AccessDecisionManagerIt is the role manager of spring security, and its corresponding abstract class isAbstractAccessDecisionManagerIf you want to customize the decision manager, you usually inherit this abstract class instead of implementing the interface.

package org.springframework.security.access.vote;

import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDecisionVoter;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.core.SpringSecurityMessageSource;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.util.Assert;

/**
 * Abstract implementation of {@link AccessDecisionManager}.
 *
 * 
 * Handles configuration of a bean context defined list of {@link AccessDecisionVoter}s
 * and the access control behaviour if all voters abstain from voting (defaults to deny
 * access).
 */
public abstract class AbstractAccessDecisionManager implements AccessDecisionManager,
		InitializingBean, MessageSourceAware {
	protected final Log logger = LogFactory.getLog(getClass());

	private List> decisionVoters;

	protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();

	private boolean allowIfAllAbstainDecisions = false;

	protected AbstractAccessDecisionManager(
			List> decisionVoters) {
		Assert.notEmpty(decisionVoters, "A list of AccessDecisionVoters is required");
		this.decisionVoters = decisionVoters;
	}

	public void afterPropertiesSet() {
		Assert.notEmpty(this.decisionVoters, "A list of AccessDecisionVoters is required");
		Assert.notNull(this.messages, "A message source must be set");
	}

	protected final void checkAllowIfAllAbstainDecisions() {
		if (!this.isAllowIfAllAbstainDecisions()) {
			throw new AccessDeniedException(messages.getMessage(
					"AbstractAccessDecisionManager.accessDenied", "Access is denied"));
		}
	}

	public List> getDecisionVoters() {
		return this.decisionVoters;
	}

	public boolean isAllowIfAllAbstainDecisions() {
		return allowIfAllAbstainDecisions;
	}

	public void setAllowIfAllAbstainDecisions(boolean allowIfAllAbstainDecisions) {
		this.allowIfAllAbstainDecisions = allowIfAllAbstainDecisions;
	}

	public void setMessageSource(MessageSource messageSource) {
		this.messages = new MessageSourceAccessor(messageSource);
	}

	public boolean supports(ConfigAttribute attribute) {
		for (AccessDecisionVoter voter : this.decisionVoters) {
			if (voter.supports(attribute)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Iterates through all AccessDecisionVoters and ensures each can support
	 * the presented class.
	 * 
	 * If one or more voters cannot support the presented class, false is
	 * returned.
	 *
	 * @param clazz the type of secured object being presented
	 * @return true if this type is supported
	 */
	public boolean supports(Class> clazz) {
		for (AccessDecisionVoter voter : this.decisionVoters) {
			if (!voter.supports(clazz)) {
				return false;
			}
		}
		return true;
	}
}

The core method issupportsMethod, one of the methods is useddecisionVotersThe type in the collection isAccessDecisionVoterThis is a voter introduced by spring security. The final decision on whether you have access or not is determined by the voter.

package org.springframework.security.access;

import java.util.Collection;

import org.springframework.security.core.Authentication;

public interface AccessDecisionVoter {
	int ACCESS_GRANTED = 1;
	int ACCESS_ABSTAIN = 0;
	int ACCESS_DENIED = -1;

	boolean supports(ConfigAttribute attribute);

	boolean supports(Class> clazz);

	int vote(Authentication authentication, S object,
			Collection attributes);
}

There are many voting machines here, the most common one isRoleVoterVoter,RoleVoterThe prefix “role” is defined_ “The core of a voter is to rely onvoteThis election method implements the parameters in the methodauthenticationIt is the user and permission information,attributesIt is the permission required to access the resource. The code circulates to determine whether the user has the permission required to access the resource. If so, it will be returnedACCESS_GRANTED, that is, they have permission.

package org.springframework.security.access.vote;

import java.util.Collection;

import org.springframework.security.access.AccessDecisionVoter;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;

public class RoleVoter implements AccessDecisionVoter {

   private String rolePrefix = "ROLE_";

   public String getRolePrefix() {
      return rolePrefix;
   }

   public void setRolePrefix(String rolePrefix) {
      this.rolePrefix = rolePrefix;
   }

   public boolean supports(ConfigAttribute attribute) {
      if ((attribute.getAttribute() != null)
            && attribute.getAttribute().startsWith(getRolePrefix())) {
         return true;
      }
      else {
         return false;
      }
   }

   public boolean supports(Class> clazz) {
      return true;
   }
   
   /**
   *Authentication is user and permission information
   *Attributes are the permissions required to access a resource
   */
   public int vote(Authentication authentication, Object object,
         Collection attributes) {
      if (authentication == null) {
         return ACCESS_DENIED;
      }
      int result = ACCESS_ABSTAIN;
      Collection extends GrantedAuthority> authorities = extractAuthorities(authentication);

      for (ConfigAttribute attribute : attributes) {
         if (this.supports(attribute)) {
            result = ACCESS_DENIED;

            // Attempt to find a matching granted authority
            for (GrantedAuthority authority : authorities) {
               if (attribute.getAttribute().equals(authority.getAuthority())) {
                  return ACCESS_GRANTED;
               }
            }
         }
      }

      return result;
   }
   Collection extends GrantedAuthority> extractAuthorities(
         Authentication authentication) {
      return authentication.getAuthorities();
   }
}

Spring seucrity provides three voting decisions, which areAffirmativeBased: you can visit by one vote;ConsensusBasedAccess is allowed only when more than half of them pass;UnanimousBased: access is allowed only when all pass. Custom decisions only need inheritanceAbstractAccessDecisionManagerAbstract class, you can customize your own voter, for example, you need to meet multiple conditions to access at the same time, and so on. You don’t need to use the voter provided by spring security.

2. Environment construction and use

2.1 quickly build spring boot + spring security environment

Open the spring boot website https://start.spring.io/ , select Java language, add spring web and spring security in dependencies, and finally click generate to download.

Java security framework

Unzip the downloaded file and open it with idea. You can see that this is a demo that can be started directly. Because we are a web project, we add an interface here to have a look.

@SpringBootApplication
@RestController
public class DemoApplication {

   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }

   @RequestMapping("/")
   public String home() {
      return "hello spring boot";
   }
}

When we start, we type in the address bar locahost:8080 It will automatically jump to the / login path, indicating that spring security has been directly involved.

Java security framework

Then we create an inheritanceWebSecurityConfigurerAdapterAt the same time, we add an interface with the path of “/ Hello”. According to the code annotation, we can see that the access to the main path of the project does not need to be verified, while the access to other paths needs to be verified. Start project, visit localhost:8080 You can go directly through, but access localhost:8080 \Hello will automatically jump to localhost:8080/login Path requires login. This shows that the security policy of spring security has taken effect, and the environment construction of spring boot and spring security has been completed.

@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

    /**
     *Interception strategy
     *Define which paths need to be intercepted and which do not
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                . antmatchers ("/"). Permitall() // the main path of the project can be released
                . anyrequest(). Authenticated() // all other requests need to be verified
                . and(). Logout(). Permitall() // allow logout to access
                . and(). Formlogin(); // allow form login
        http.csrf (). Disable(); // turn off CSRF authentication
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        /**
         *Ignore static resource interception
         */
        web.ignoring().antMatchers("/js/**", "/css/**");
    }
}

2.2 common case implementation

2.2.1 as long as you can log in

As long as you log in, you can access all the resource paths of the project, and you don’t need to write a separate login page. Here, you will use the memory based authentication provided by spring security. staySpringSecurityConfigClassconfigure(AuthenticationManagerBuilder auth)This method. After spring security 5.0, a variety of encryption methods have been added and the default password format has been changed. The new password storage format is “{ID}…” . the ID in the front is the encryption method. The ID can be bcrypt, sha256, etc., followed by the encrypted password. That is to say, when the program gets the password, it will first look for the ID included by “{” and “}” to determine how the password is encrypted. If it can not be found, the ID will be considered as null. At this time, the program will report an error: there is no passwordencoder mapped for the ID “null”. In practical application, you can also customize the encryption method, only need to inheritPasswordEncoderInterface.

@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        //Create a user with the user name of admin, password of 123456 and role of admin
       auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
                .withUser("admin")
                .password(new BCryptPasswordEncoder().encode("123456"))
                .roles("ADMIN");

        //Multiple users can be specified
        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
                .withUser("zhangsan")
                .password(new BCryptPasswordEncoder().encode("123456"))
                .roles("DEMO");
    }
}

2.2.2 there are specified roles, and each role has specified permissions

To add a qualified role request, only those with the admin role can access it byRoleVoterThe prefix defined in the previous custom decision. At the same time, it is also important to note that the@PreAuthorizeThis annotation must be added to the class@EnableGlobalMethodSecurity(prePostEnabled = true)annotation@PreAuthorizeWill take effect. In this way, admin users can access / roleauth, but Zhangsan can’t access / roleauth.

@SpringBootApplication
@RestController
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class DemoApplication {
    /**Middle code omitted**/
    
	@PreAuthorize("hasRole('ROLE_ADMIN')")
	@RequestMapping("/roleAuth")
	public String role() {
		return "admin auth";
	}
}

In the actual scenario, user roles are generally stored in the database. As mentioned above, the database management of spring security needs to be implementedUserDetailsServiceInterface, define database related query, returnUserDetailsObject.

package com.mall.demo;

import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;

@Component
public class MyUserService implements UserDetailsService {

    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        return null;
    }
}
@Autowired
private MyUserService myUserService;

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {

    auth.userDetailsService(myUserService);
    /**
     *Default database validation provided by spring security
     */
    auth.jdbcAuthentication()
            . usersbyusernamequery (") // query users
            . authoritiesbyusernamequery ("); // query permissions
}

Before we go back to security, we can use the spring database configuration@PreAuthorizeThis annotation controls whether a method can be called. In fact, spring security provides four such annotations, namely@PreAuthorize@PostAuthorize@PreFilter@PostFilter@PreAuthorizeand@PostAuthorizeIs used to check the permissions before and after a method call,@PreFilterand@PostFilterIs used to filter the parameters or return values of the collection class.

//The ID parameter passed in is less than 10
//Incoming username = current user name
//The user name of the user object passed in = Zhangsan
@PreAuthorize("#id<10 and principal.username.equals(#username) and #user.username.equals('zhangsan')")
//Verify that the returned result is even
@PostAuthorize("returnObject%2==0")
@RequestMapping("/test1")
public Integer test1(Integer id, String username, User user) {
   return id;
}

//Filter incoming parameters, leaving even numbers
@PreFilter("filterObject%2==0")
//Filter returns the number that is divisible by 4
@PostFilter("filterObject%4==0")
@RequestMapping("/test2")
public List test2(List idList) {
   return idList;
}