spring-security (twenty-one) core Filter-UsernamePasswordAuthenticationFilter

1. UsernamePasswordAuthenticationFilter functions and properties
So far , we have discussed three main filters. When using the default configuration, spring security will automatically add these three filters to us. Now our filter is still missing a filter that handles user authentication. , below we mainly discuss the most commonly used authentication filter-UsernamePasswordAuthenticationFilter.

1. Important attributes
  • AuthenticationManager is used for authentication, by default it is ProviderManager
  • RememberMeServices If the remember function is enabled, spring will inject us a TokenBasedRememberMeServices. If the remember function is not enabled, the default NullRememberMeServices is used.
  • RequestMatcher is used to determine whether the current HttpServletRequest request needs to be processed with the current filter. The default matching URL is /login, and the httpMethod is a POST request.
  • SessionAuthenticationStrategy After successful authentication, the onAuthentication of this class will be called to do some session processing
  • AuthenticationSuccessHandler is a post-processor for successful authentication. By default, SavedRequestAwareAuthenticationSuccessHandler is used, which will redirect the user to the original request that caused the authentication process and continue the previous operation.
  • AuthenticationFailureHandler Handler after authentication failure, redirect the user to defaultFailureUrl by default, such as /login?error

2. Processing logic
2.1 When a request enters this filter, first use the requiresAuthenticationRequestMatcher attribute to match the request. If the match is successful, the logic in the filter will continue to be executed. If it does not match, the next filter will be executed directly.
2.2 If 2.1 matches successfully, start the authentication process.
2.2.1 First get the username and password from the request (the parameter name can be customized), and assemble it into a UsernamePasswordAuthenticationToken.
2.2.2 If there is additional information, you need to save it and call authenticationDetailsSource.buildDetails to append the build details. After 2.2.3 in the Token,
call the authenticationManager.authenticate method for authentication. After the authentication is successful, this method will return us an assembled Authentication object .
2.2.3.1 After the authentication is successful, execute the logic
    a. Call the sessionStrategy.onAuthentication method to perform some processing on the session. , this function is more important, and will be discussed in detail below
    . b. Store the assembled Authentication in the SecurityContextHolder
    c. Call the loginSuccess method of rememberMeServices. If the remember function is configured, our username and password will be serialized and stored in the In the cookie, the corresponding key is remember-me
    d. Then call the onAuthenticationSuccess method of successHandler, and continue to execute the original request that caused the authentication process by default.
2.2.3.2 Execution logic after authentication failure
   a. Clear the authentication information in the SecurityContextHolder
   b. Execute the rememberMeServices.loginFail method to set the key in the cookie to remember-me
3. About SessionAuthenticationStrategy 3.1 In the default
configuration, spring security will build ChangeSessionIdAuthenticationStrategy for us in servelet3.1+ environment (SessionFixationProtectionStrategy is built under lower version servlets) to deal with session fixation attacks. If csrf is enabled, spring will Let us enable a CsrfAuthenticationStrategy. If concurrent session control is enabled, spring will inject ConcurrentSessionControlAuthenticationStrategy and RegisterSessionAuthenticationStrategy for me, so after enabling the csrf and currency session functions, there will eventually be four SessionAuthenticationStrategy, and then spring will combine these four SessionAuthenticationStrategy into a A CompositeSessionAuthenticationStrategy is assigned to this authentication filter.
The final results are listed as follows:
  • ConcurrentSessionControlAuthenticationStrategy When it is found that the same user has reached the maximum number of concurrent logins, the session with the earliest last active time of the user is set to expire, and the session information corresponding to the user is obtained from the SessionRegistry.
  • ChangeSessionIdAuthenticationStrategy Modify sessionId after successful user authentication to prevent session fixation attacks
  • RegisterSessionAuthenticationStrategy After the user is authenticated successfully, the session information corresponding to the user is stored in the SessionRegistry for use by the ConcurrentSessionControlAuthenticationStrategy
  • CsrfAuthenticationStrategy, after the user authentication is successful, clear the original csrf token, then regenerate a csrf token, store it in the CsrfTokenRepository and set it in the request for use by the CsrfFilter, and the subsequent csrf Tokens are managed by the CsrfFilter


The SessionRegistry corresponding to ConcurrentSessionControlAuthenticationStrategy and RegisterSessionAuthenticationStrategy is the same instance, and the default implementation is SessionRegistryImpl. There are mainly two hashmaps in this class, one is the correspondence between user and sessionId, and the other is the correspondence between session and SessionInformation
/** <principal:Object,SessionIdSet> */
private final ConcurrentMap<Object, Set<String>> principals = new ConcurrentHashMap<Object, Set<String>>();
/** <sessionId:Object,SessionInformation> */
private final Map<String, SessionInformation> sessionIds = new ConcurrentHashMap<String, SessionInformation>();

RegisterSessionAuthenticationStrategy will call the registerNewSession method of this class to append a corresponding record of the current sessionId and SessionInformation to the sessionIds corresponding to the user.
ConcurrentSessionControlAuthenticationStrategy obtains all sessionIds corresponding to the current user after successful authentication, so as to determine whether the size reaches the maximum limit for concurrent login control.
2. In the spring boot environment, how does the filter use the Java config mechanism to be added to the servlet to intercept our requests?
In the previous chapter (spring-security (16) Filter configuration principle) , we know that the spring security-related Filter is to call the build of HttpSecurity in the build method of WebSecurity to sort the filter list appended to HttpSecurity and build it into SecurityFilterChain, then append all SecurityFilterChains to FilterChainProxy, and finally register them to ServletContext through DelegatingFilterProxy. Let's mainly see how this class is added to the filter list of HttpSecuriy.
1. Starting from our configuration entry WebSecurityConfigurerAdapter class, when using the default configuration, in the configure(HttpSecurity http) method of this class (most of our customized processing is implemented by overriding this method), http. formLogin() method
public FormLoginConfigurer<HttpSecurity> formLogin() throws Exception {
    return getOrApply(new FormLoginConfigurer<HttpSecurity>());
}

In this method, a configuration class FormLoginConfigurer that implements the SecurityConfigurer interface is created. By calling the getOrApply method, it is finally added to the configurers property of HttpSecurity. Through this configuration class, we can also set a custom login page, set the request path for authentication processing, Set the jump address after successful login (if not set, it will jump to the address that caused the authentication request), set the default jump address after login failure, etc.
2. Constructor of the FormLoginConfigurer class
public FormLoginConfigurer() {
    super(new UsernamePasswordAuthenticationFilter(), null);
    usernameParameter("username");
    passwordParameter("password");
}

In the constructor, a UsernamePasswordAuthenticationFilter is created for us, and the parameter names corresponding to the default username and password are set to username and password.
3. See how the properties corresponding to this filter are set.
When WebSecurity builds HttpSecurity, it will call the build method of HttpSecurity. This method will first execute the configure() method of HttpSecurity, which is to call the configure method of each SecurityConfigurer in the configurers property in turn
private void configure() throws Exception {
  Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();
  for (SecurityConfigurer<O, B> configurer : configurers) {
     configurer.configure((B) this);
  }
}

Let's take a look at the configure method of FormLoginConfigurer, the specific logic is in its parent class AbstractAuthenticationFilterConfigurer
@Override
public void configure(B http) throws Exception {
	PortMapper portMapper = http.getSharedObject(PortMapper.class);
	if (portMapper != null) {
		authenticationEntryPoint.setPortMapper(portMapper);
	}
	authFilter.setAuthenticationManager(http
			.getSharedObject(AuthenticationManager.class));
	authFilter.setAuthenticationSuccessHandler(successHandler);
	authFilter.setAuthenticationFailureHandler(failureHandler);
	if (authenticationDetailsSource != null) {
	authFilter.setAuthenticationDetailsSource(authenticationDetailsSource);
	}
	SessionAuthenticationStrategy sessionAuthenticationStrategy = http
			.getSharedObject(SessionAuthenticationStrategy.class);
	if (sessionAuthenticationStrategy != null) {
authFilter.setSessionAuthenticationStrategy(sessionAuthenticationStrategy);
	}
	RememberMeServices rememberMeServices = http
			.getSharedObject(RememberMeServices.class);
	if (rememberMeServices != null) {
		authFilter.setRememberMeServices(rememberMeServices);
	}
	F filter = postProcess(authFilter);
	http.addFilter(filter);
}

Obviously in this configure method, AuthenticationManager, AuthenticationSuccessHandler, AuthenticationFailureHandler, SessionAuthenticationStrategy, RememberMeServices and other required properties we saw earlier are set for the filter. Except SessionAuthenticationStrategy, the setting of other attributes is relatively simple. The setting logic of SessionAuthenticationStrategy needs to refer to the init and configure methods of SessionManagementConfigurer and the configure method of CsrfConfigurer, which will not be detailed here.
At the end of the above method, the configured filter is added to the filter list of HttpSecurity through http.addFilter, so that our request can be filtered like other filters.

The above is the main content of UsernamePasswordAuthenticationFilter. This filter is also the main processing class of our most commonly used username and password authentication methods. Later, we will explain other authentication methods and corresponding filters.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326133321&siteId=291194637