Important concepts related to certification

SecurityContextHolder

At the heart of the Spring Security authentication model is the SecurityContextHolder. It contains the SecurityContext.

Spring Security’s SecurityContextHolder, which stores the details of the authenticated person.

SecurityContext

The SecurityContext is available from SecurityContextHolder. The SecurityContext contains an authentication object.

Authentication

Authentication has two main uses in Spring Security:

  • AuthenticationManagerIs used to provide the user’s authentication credentials. When used in this context,IsAuthenticated ()Returns false.
  • Represents the currently authenticated user. Available from theSecurityContextGet the current authentication.

It contains three pieces:

  • principal

    User abstraction. When using a username/password for authentication, it is usually an instance of UserDetails.

  • credentials

    Usually a password. In many cases, this content is cleared after user authentication to ensure that it does not leak.

  • authorities

    GrantedAuthoritys are permissions granted to users. Usually characters.

GrantedAuthority

GrantedAuthoritys are permissions granted to users. Usually characters.

Spring Security’s filters need to be able to identify which resources these permissions can access and throw exceptions if they are insufficient.

When username/password-based authentication is used, GrantedAuthoritys are usually loaded by the UserDetailsService.

AuthenticationManager

AuthenticationManager is the API used to define how Spring Security’s filters perform authentication. After validation, the controller that calls the AuthenticationManager (the Filters of Spring Security) sets the Authentication returned on the SecurityContextHolder.

The most common implementation is ProviderManager.

ProviderManager

The ProviderManager delegates to the AuthenticationProvider list for authentication. Each AuthenticationProvider can indicate that authentication should be successful, failed, or that it cannot make a decision, and allow the downstream AuthenticationProvider to make that decision.

Each AuthenticationProvider can perform a specific type of authentication. For example, one AuthenticationProvider might be able to validate user names/passwords, while another might be able to validate SAML assertions.

AuthenticationProvider

Multiple AuthenticationProviders can be injected into the ProviderManager. Each AuthenticationProvider performs a specific authentication type. DaoAuthenticationProvider support, for example, based on user name/password authentication, but JwtAuthenticationProvider support to JWT token authentication.

AuthenticationEntryPoint

AuthenticationEntryPoint is used to send an HTTP response to request credentials from a client. When an unauthenticated user accesses a system path, the AuthenticationEntryPoint implementation might perform a redirect to the login page, respond with www-Authenticate headers, and so on.

AbstractAuthenticationProcessingFilter

AbstractAuthenticationProcessingFilter were used as basis for filter, is used to validate user credentials, may submit to it for any authentication request for authentication.

  1. When the user submits the Authentication credentials, AbstractAuthenticationProcessingFilter will create an Authentication from to verify it. Create the authentication type depends on the subclass AbstractAuthenticationProcessingFilter.

    UsernamePasswordAuthenticationFilter according to in it, for example, submit the user name and password to create a UsernamePasswordAuthenticationToken.

  2. Pass Authentication to the AuthenticationManager for Authentication.

  3. If the authentication fails, the process ends and the login fails.

    • remove SecurityContextHolder
    • callRememberMeServices.loginFail. ifremember meIf it is not configured, it will not be called.
    • callAuthenticationFailureHandler
  4. If the verification succeeds, the login succeeds

    • Notify the login toSessionAuthenticationStrategy
    • theAuthenticationSet it toSecurityContextHolderOn.
    • callRememberMeServices.loginSuccess. ifremember meIf it is not configured, it will not be called.
    • ApplicationEventPublisherTo release aInteractiveAuthenticationSuccessEvent.
    • callAuthenticationSuccessHandler

BCryptPasswordEncoder

The BCryptPasswordEncoder implementation hashes the password using the widely supported Bcrypt algorithm. And that’s what we use to encrypt passwords.

Username/Password Authentication

One of the most common ways to authenticate a user is to authenticate a user name and password. As a result, Spring Security provides full support for authentication using user names and passwords.

Get the username and password from HttpServletRequest with the following mechanism:

  • Form Login
  • Basic Authentication
  • Digest Authentication

Storage mechanisms provide the following:

  • Memory-based simple storage (In-Memory Authentication)
  • Relational database storage (JDBC Authentication)
  • Custom data stores (UserDetailsService)

Memory-based simple storage

The Spring Security default password is generated randomly and printed to the console. That is, memory-based simple storage.

2020-11- 0919:18:39.634  INFO 17384 --- [           main] .s.s.UserDetailsServiceAutoConfiguration : Using generated security password: 59423ac9-f9a0-41b5-a4c9-f508102217c4
Copy the code

We open UserDetailsServiceAutoConfiguration class, main methods are as follows

@Bean
@ConditionalOnMissingBean( type = "org.springframework.security.oauth2.client.registration.ClientRegistrationRepository")
@Lazy
    public InMemoryUserDetailsManager inMemoryUserDetailsManager(SecurityProperties properties, ObjectProvider
       
         passwordEncoder)
        {
    // Get user from the configuration file
        SecurityProperties.User user = properties.getUser();
        List<String> roles = user.getRoles();
    // Create memory user manager
        return new InMemoryUserDetailsManager(
                User.withUsername(user.getName()).password(getOrDeducePassword(user, passwordEncoder.getIfAvailable()))
                        .roles(StringUtils.toStringArray(roles)).build());
    }
 
    private String getOrDeducePassword(SecurityProperties.User user, PasswordEncoder encoder) {
    String password = user.getPassword();
    If the password is automatically generated, print it to the console
        if (user.isPasswordGenerated()) {
            logger.info(String.format("%n%nUsing generated security password: %s%n", user.getPassword()));
        }
        if(encoder ! =null || PASSWORD_ALGORITHM_PATTERN.matcher(password).matches()) {
            return password;
        }
        return NOOP_PASSWORD_PREFIX + password;
    }
Copy the code

Let’s deep to see the source code, just need guidance, the class to Spring into a InMemoryUserDetailsManager memory user manager, and created a user. So that’s how you do username/password login.

Spring Security InMemoryUserDetailsManager UserDetailsService is achieved, to support for in memory based on user name/password authentication.

The same is true for configuring user names and passwords in configuration files.

Customize the storage login process

For username/password login, Spring Security also provides several ways to store users: in-memory storage, connecting to a relational database through JDBC, custom storage, and so on. The most commonly used is custom storage, in fact, is stored in the database, their own storage, their own access.

The figure on the official website allows us to clearly understand the authentication process of custom storage.

  1. The authentication filter that reads the user name and password willUsernamePasswordAuthenticationTokenPassed to theAuthenticationManager, the identity manager byProviderManagerThe implementation.
  2. ProviderManagerThe use ofAuthenticationProviderThe implementation of the classDaoAuthenticationProvider
  3. DaoAuthenticationProviderUserDetailsServiceCall method fetchUserDetails.
  4. DaoAuthenticationProviderusePasswordEncoderValidate what was returned in the previous stepUserDetailsPassword on.
  5. After successful authentication, the type of authentication returned isUsernamePasswordAuthenticationTokenAnd its body is configured by usUserDetailsServiceThe returnedUserDetails. And finally, the returnUsernamePasswordAuthenticationTokenWill be authenticated by the filter inSecurityContextHolderOn the set.

Therefore, the UserDetailService and UserDetails are generally extended for custom storage logins.

Important concepts related to authorization

Authentication contains GrantedAuthority, which indicates the permission of the subject.

The GrantedAuthority object is inserted into the Authentication object by the AuthenticationManager and read by the AccessDecisionManager later when authorization decisions are made.

public interface GrantedAuthority extends Serializable {
    String getAuthority(a);
}
Copy the code

Spring Security includes an implementation of GrantedAuthority, namely SimpleGrantedAuthority, whose constructor accepts a String. In Spring Security architectures, the SimpleGrantedAuthority is generally used.

AccessDecisionManager

Spring Security provides interceptors for controlling access, such as intercepting HTTP requests.

The AccessDecisionManager by the AbstractSecurityInterceptor calls, and decision whether the request is allowed.

The AccessDecisionManager interface contains three methods:

// Decides whether the request is allowed
void decide(Authentication authentication, Object secureObject, Collection
       
         attrs)
        throws AccessDeniedException;
/ / in the beginning, the AbstractSecurityInterceptor will invoke the support (ConfigAttribute) method, to determine whether the AccessDecisionManager ConfigAttribute can handle the transfer.
boolean supports(ConfigAttribute attribute);
 
// The security interceptor implementation calls the support (Class) method to ensure that the configured AccessDecisionManager supports the type of security object that the security interceptor will display.
boolean supports(Class clazz);
Copy the code

FilterSecurityInterceptor

FilterSecurityInterceptor HttpServletRequests provide authorization. It is one of the Security filters.

  1. FilterSecurityInterceptorfromSecurityContextHolderTo obtainAuthentication.
  2. FilterSecurityInterceptorAccording to pass toFilterSecurityInterceptorIn theHttpServletRequest.HttpServletResponseandFilterChainTo create aFilterInvocation.
  3. willFilterInvocationPassed to theSecurityMetadataSourceIn order to getConfigAttributeS.
  4. willAuthentication.FilterInvocationandConfigAttributesPassed to theAccessDecisionManager.
  5. If authorization is rejected, it is thrownAccessDeniedException.ExceptionTranslationFilterTo deal withAccessDeniedException.
  6. If access is granted,FilterSecurityInterceptorContinue to useFilterChainAllows the application to process normally.

By default, Spring Security’s authorization will require authentication for all requests.

FilterInvocationSecurityMetadataSource

As stated above, get ConfigAttributes using SecurityMetadataSource.

FilterInvocationSecurityMetadataSource inheritance SecurityMetadataSource and no extension methods. When extending, this method is typically implemented to match roles with urls.

public interface FilterInvocationSecurityMetadataSource extends SecurityMetadataSource {}Copy the code