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:
AuthenticationManager
Is used to provide the user’s authentication credentials. When used in this context,IsAuthenticated ()
Returns false.- Represents the currently authenticated user. Available from the
SecurityContext
Get 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.
-
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.
-
Pass Authentication to the AuthenticationManager for Authentication.
-
If the authentication fails, the process ends and the login fails.
- remove
SecurityContextHolder
- call
RememberMeServices.loginFail
. ifremember me
If it is not configured, it will not be called. - call
AuthenticationFailureHandler
- remove
-
If the verification succeeds, the login succeeds
- Notify the login to
SessionAuthenticationStrategy
- the
Authentication
Set it toSecurityContextHolder
On. - call
RememberMeServices.loginSuccess
. ifremember me
If it is not configured, it will not be called. ApplicationEventPublisher
To release aInteractiveAuthenticationSuccessEvent
.- call
AuthenticationSuccessHandler
- Notify the login to
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.
- The authentication filter that reads the user name and password will
UsernamePasswordAuthenticationToken
Passed to theAuthenticationManager
, the identity manager byProviderManager
The implementation. ProviderManager
The use ofAuthenticationProvider
The implementation of the classDaoAuthenticationProvider
。DaoAuthenticationProvider
从UserDetailsService
Call method fetchUserDetails
.DaoAuthenticationProvider
usePasswordEncoder
Validate what was returned in the previous stepUserDetails
Password on.- After successful authentication, the type of authentication returned is
UsernamePasswordAuthenticationToken
And its body is configured by usUserDetailsService
The returnedUserDetails
. And finally, the returnUsernamePasswordAuthenticationToken
Will be authenticated by the filter inSecurityContextHolder
On 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.
FilterSecurityInterceptor
fromSecurityContextHolder
To obtainAuthentication
.FilterSecurityInterceptor
According to pass toFilterSecurityInterceptor
In theHttpServletRequest
.HttpServletResponse
andFilterChain
To create aFilterInvocation
.- will
FilterInvocation
Passed to theSecurityMetadataSource
In order to getConfigAttribute
S. - will
Authentication
.FilterInvocation
andConfigAttributes
Passed to theAccessDecisionManager
. - If authorization is rejected, it is thrown
AccessDeniedException
.ExceptionTranslationFilter
To deal withAccessDeniedException
. - If access is granted,
FilterSecurityInterceptor
Continue to useFilterChain
Allows 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