I. Structure overview

The problem Spring Security addresses is secure access control, which essentially intercepts all incoming requests to verify that each request has access to the desired resource. Spring Security protects Web resources by using filters.

When the initializationSpring Security, one is createdSpringSecurityFilterChainIs a filter of typeorg.springframework.security.web.FilterChainProxyAnd it didjavax.servlet.Filter, so external requests go through this class.FilterChainProxyIt’s an agent. What really works isFilterChainProxyIn theSecurityFilterChainAll of themFilter. At the same time theseFilterAs aBeanbeSpringManagement, they areSpring SecurityThe core of the. Instead of handling user authentication and authorization directly, they hand it over to the authentication manager (AuthenticationManager) and decision manager (AccessDecisionManage) for processing. Below isFilterChainProxyUML diagrams within the correlation:

Spring SecurityThe function is realized by a series of filter chains cooperating with each other:

The mainFilterFunction introduction:

Role name SecurityContextPersistenceFilter this Filter is the entry and exit of the interception process, will be at the beginning of the request from the configured SecurityContextRepository SecurityContext, Then set it to the SecurityContextHolder. At the completion of a request to hold SecurityContextHolder SecurityContext again saved to the configured SecurityContextRepository, Also clears the SecurityContext held by securityContextHolder; UsernamePasswordAuthenticationFilter from the form is submitted for certification. The form must provide the corresponding user name and code, its internal and login for processing after the success or failure of AuthenticationSuccessHandler and AuthenticationFailureHandler, these can make relevant changes according to the requirements; FilterSecurityInterceptor is used to protect a web resource, use the AccessDecisionManager to grant access to the current user, surface before a detailed introduction has been made. ExceptionTranslationFilter capture from FilterChain all exceptions, and processing. But it only handles two types of exceptions: AuthenticationException and AccessDeniedException, and it continues to throw the others.

Second, the certification process

Steps of the certification process:

(1) after the user submits the account password, be SecurityFilterChain acquisition to the UsernamePasswordAuthenticationFilter filters, encapsulated in the Authentication request object.

② The filter then submits Authentication to the AuthenticationManager for Authentication.

③ After successful authentication, the AuthenticationManager returns a message filled with information (identity, permission…). Authentication instance of.

(4) SecurityContextHolder container will populate the information Authentication, through SecurityContextHolder. GetContext. SetAuthetication (…). Method is set to.

It can be seen that the AuthenticationManager interface is the core interface of authentication and the starting point of initiating authentication. Its implementation class is ProviderManager. Spring Security supports multiple authentication methods, so ProviderManager maintains a List< AuthenticationProvider >
with multiple authentication methods. Ultimately, the actual authentication is done by the AuthenticationProvider. Web form the corresponding AuthenticationProvider implementation class for the DaoAuthenticationProvider, its internal also maintains a UserDetailService responsible for populated UserDetails access, Finally, the AuthenticationProvider populates the UserDetails into Authentication.

The general relationship between the authentication core components is as follows:

2.1 the Authentication

Authentication The Authentication information interface is defined as follows:

public interface Authentication extends Principal.Serializable {
    Collection<? extends GrantedAuthority> getAuthorities();
    Object getCredentials(a);
    Object getDetails(a);
    Object getPrincipal(a);
    boolean isAuthenticated(a);
    void setAuthenticated(boolean var1) throws IllegalArgumentException;
}
Copy the code

Authentication is the interface in the Spring Security package, and the direct inheritance of Principal is in the java.security package. It represents an abstract Principal identity. Any Principal has a name and therefore contains a getName() method.

The getAuthorities() list of permission information, which is typical of the GrantedAuthority interface by default, is a set of strings that represent permission information. GetCredentials () Credentials, a string of passwords entered by users that are usually removed after authentication, To ensure the security of getDetails() details, the implementation interface in Web applications is usually WebAuthenticationDetails, which records the identity of the visitor’s IP address getPrincipal(), and in most cases returns the implementation class of the UserDetails interface. UserDetails represents the user’s details, and the login user information can be obtained from this interface

2.2 AuthenticationProvider

As you can see from the previous authentication process, the AuthenticationManager delegates authentication to the AuthenticationProvider.

The AuthenticationProvider interface is defined as follows:

public interface AuthenticationProvider {
    Authentication authenticate(Authentication var1) throws AuthenticationException;
    boolean supports(Class
        var1);
}
Copy the code

The authenticate() method defines the Authentication process. The parameter is Authentication, which contains the user and password submitted by the user. The return value is also an Authentication, which is generated by reassembling the user’s permission and other information after successful Authentication.

Different authentication methods use the AuthenticationProvider of different implementation classes, and each AuthenticationProvider needs to implement the support() method to indicate which authentication method it supports. If we use forms Authentication, submit your request in SpringSecurity generates UsernamePasswordAutheticationToken, it is an Authentication.

2.3 UserDetailsService

DaoAuthenticationProvider dealt with Web forms authentication logic, certification a Authencation after success (UsernamePasswordAuthenticationToken implementation),

DaoAuthenticationProvider contains a UserDetailsService instance, it is responsible for user information extraction according to the user name UserDetailService instance, it is responsible for user information extraction according to the user name populated UserDetails (including the password). DaoAuthenticationProvider to contrast UserDetailsService extracting user password password matches with the user submits as the authentication key to the success of the basis, Therefore, you can customize the implementation class of UserDetailsService to achieve customized identity authentication.

UserDetailsService interface definition:

public interface UserDetailsService {
    UserDetails loadUserByUsername(String var1) throws UsernameNotFoundException;
}
Copy the code

The UserDetailsService is only responsible for loading user information from a specific place (usually a database), and that’s it. And DaoAuthenticationProvider responsibility is bigger, it completed a complete certification process, at the same time, will fill the populated UserDetails to Authentication.

2.4 populated UserDetails

UserDetails interface definition:

public interface UserDetails extends Serializable {
    Collection<? extends GrantedAuthority> getAuthorities();
    String getPassword(a);
    String getUsername(a);
    boolean isAccountNonExpired(a);
    boolean isAccountNonLocked(a);
    boolean isCredentialsNonExpired(a);
    boolean isEnabled(a);
}
Copy the code

It is similar to the Authentication interface in that both have username, authorities. The getCredentials() in Authentication need to be treated differently from the getPassword() in UserDetails. The former are the password credentials submitted by the user and the latter are the passwords actually stored by the user. Authentication is actually a comparison between the two. The getAuthorities() of Authentication are really formed by the getAuthorities() of UserDetails. The UserDetails in UserDetails are populated after AuthenticationProvider authentication. By implementing the UserDetailsService and UserDetails, you can customize the method of obtaining user information and user information fields.

Spring Security provided by InMemoryUserDetailsManager certification (memory), JdbcUserDetailsManager (JDBC certification) is UserDetailsService implementation class, The main difference between memory and database load users.

2.5 PasswordEncoder

DaoAuthenticationProvider Authentication processor through UserDetailsService get populated UserDetails, how and the password Authentication compare?

Spring Security in order to adapt to a variety of encryption type, DaoAuthenticationProvider password by PasswordEncoder interface matches method of comparison, The details of the password comparison depend on the implementation class of the PasswordEncoder interface:

public interface PasswordEncoder {
    String encode(CharSequence var1);
    boolean matches(CharSequence var1, String var2);
    default boolean upgradeEncoding(String encodedPassword) {
        return false; }}Copy the code

Spring Security provides a number of PasswordEncoder implementation classes. You can inject PasswordEncoder into the IOC container:

@Configuration
public class WebSecurityConfig {

    @Bean
    public PasswordEncoder passwordEncoder(a) {
        returnNoOpPasswordEncoder.getInstance(); }}Copy the code

NoOpPasswordEncoder compares the plaintext entered by the user directly to the data in the database.

In actual projects, BCryptPasswordEncoder, Pbkdf2PasswordEncoder, and SCryptPasswordEncoder are recommended. Using these Passwordencoders, passwords stored in the database need to be encrypted using the corresponding encryption method.