spring security integration oauth2 practical logic flow summary

  Originally wanted to write about spring security source to read the article, but a matter of time considering the one hand, on the other hand, for practical purposes, there is going to start recording at the relevant loading process, request authentication and authorization processes.

Summarized as follows:

1. Start Process Overview

2, token acquisition process analysis

3, requested authentication and authorization process analysis

 

First, start the process overview

  The main focus of the boot process involves loading configuration information and build a filter chain .

spring security framework is the core of the filter chain! It is the focus of the analysis process start and end debugging code to be concerned about.

First Viewpoint inlet class org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration, methods setFilterChainProxySecurityConfigurer there

for (SecurityConfigurer<Filter, WebSecurity> webSecurityConfigurer : webSecurityConfigurers) {
            webSecurity.apply(webSecurityConfigurer);
        }

Configuration will org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter type (security-related), org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter type configuration (server resources), org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter type configuration (associated authorization server) are fitted into org.springframework.security.config.annotation.web.builders.WebSecurity object.

Stay tuned method springSecurityFilterChain ,

 1 public Filter springSecurityFilterChain() throws Exception {
 2         boolean hasConfigurers = webSecurityConfigurers != null
 3                 && !webSecurityConfigurers.isEmpty();
 4         if (!hasConfigurers) {
 5             WebSecurityConfigurerAdapter adapter = objectObjectPostProcessor
 6                     .postProcess(new WebSecurityConfigurerAdapter() {
 7                     });
 8             webSecurity.apply(adapter);
 9         }
10         return webSecurity.build();
11     }

Follow up on line 10, enter org.springframework.security.config.annotation.AbstractSecurityBuilder # build,

1 public final O build() throws Exception {
2         if (this.building.compareAndSet(false, true)) {
3             this.object = doBuild();
4             return this.object;
5         }
6         throw new AlreadyBuiltException("This object has already been built");
7     }

Continues into doBuild () method,

 1 protected final O doBuild() throws Exception {
 2         synchronized (configurers) {
 3             buildState = BuildState.INITIALIZING;
 4 
 5             beforeInit();
 6             init();
 7 
 8             buildState = BuildState.CONFIGURING;
 9 
10             beforeConfigure();
11             configure();
12 
13             buildState = BuildState.BUILDING;
14 
15             O result = performBuild();
16 
17             buildState = BuildState.BUILT;
18 
19             return result;
20         }
21     }

Since spring security configuration are generally inherited org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter, look here for it. Key see above Line 6 init (), line 11 configure (), line 15 performBuild (). init () method will trigger org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter # init method,

 1 public void init(final WebSecurity web) throws Exception {
 2         final HttpSecurity http = getHttp();
 3         web.addSecurityFilterChainBuilder(http).postBuildAction(new Runnable() {
 4             public void run() {
 5                 FilterSecurityInterceptor securityInterceptor = http
 6                         .getSharedObject(FilterSecurityInterceptor.class);
 7                 web.securityInterceptor(securityInterceptor);
 8             }
 9         });
10     }

Then look getHttp () method, the following code will be constructed which contains the default filter chain,

 1 http
 2                 .csrf().and()
 3                 .addFilter(new WebAsyncManagerIntegrationFilter())
 4                 .exceptionHandling().and()
 5                 .headers().and()
 6                 .sessionManagement().and()
 7                 .securityContext().and()
 8                 .requestCache().and()
 9                 .anonymous().and()
10                 .servletApi().and()
11                 .apply(new DefaultLoginPageConfigurer<>()).and()
12                 .logout();

Each step corresponds to see out of the filter constructed by debug, as shown below:

Meanwhile getHttp () method finally there

1 configure(http)

Here performs org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter type of configuration (security-related), org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter type configuration (server resources) , org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter configure many types of configuration methods (authorization server-related).

This generally explains the creation and loading default filter chain processes the configuration information.

 

Two, token acquisition process analysis

  This article is the use of password authentication mode oauth2 (Password Grant Type), in short, when you first authenticate the user passes username and password, authentication server returns a token, take this token later when a user requests access to a resource, you can access its privileged resources. Details Reference: https://developer.okta.com/blog/2018/06/29/what-is-the-oauth2-password-grant  .

Therefore, this article refers to single sign-on process is to get the token of.

token is acquired links: / oauth / token, the corresponding code org.springframework.security.oauth2.provider.endpoint.TokenEndpoint # postAccessToken spring-security-oauth2 jar package;

To learn the entire flow through the filter, the filter can break track to perform the filter chain in the org.springframework.security.web.FilterChainProxy, specifically in org.springframework.security.web.FilterChainProxy.VirtualFilterChain #doFilter breakpoint in the method .

Here I mainly want to know the generated token, it is the breakpoint directly, go step by step in postAccessToken method until the following line of code,

OAuth2AccessToken token = getTokenGranter().grant(tokenRequest.getGrantType(), tokenRequest);

Here is where the request is granted token, step by step to break with the inside, and finally back to the method org.springframework.security.oauth2.provider.CompositeTokenGranter # grant,

1 public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) {
2         for (TokenGranter granter : tokenGranters) {
3             OAuth2AccessToken grant = granter.grant(grantType, tokenRequest);
4             if (grant!=null) {
5                 return grant;
6             }
7         }
8         return null;
9     }

FIG tokenRequest herein below,

Literally see probably see five kinds of grant types that correspond oauth2 of grant types reference https://oauth.net/2/grant-types/  , we Granter password mode corresponds to the last figure above, the method org.springframework the third line different granter .security.oauth2.provider.CompositeTokenGranter # grant is based on grant type to select the appropriate granter, if not directly match return null. The method proceeds to a final grant Granter below,

protected OAuth2AccessToken getAccessToken(ClientDetails client, TokenRequest tokenRequest) {
        return tokenServices.createAccessToken(getOAuth2Authentication(client, tokenRequest));
    }

 

Finally into getOAuth2Authentication (client, tokenRequest), the method has the following code,

userAuth = authenticationManager.authenticate(userAuth);

AuthenticationManager above is a org.springframework.security.authentication.ProviderManager, encapsulates several org.springframework.security.authentication.AuthenticationProvider, provider authentication and returns a non-null Authentication is finished continue certification, we used in the project is org.springframework. security.authentication.dao.DaoAuthenticationProvider, she would do all kinds of check (for example configuration file is the Checker), user password verification, etc.;

接着进入org.springframework.security.oauth2.provider.token.DefaultTokenServices#createAccessToken(org.springframework.security.oauth2.provider.OAuth2Authentication)方法,

 1 @Transactional
 2     public OAuth2AccessToken createAccessToken(OAuth2Authentication authentication) throws AuthenticationException {
 3 
 4         OAuth2AccessToken existingAccessToken = tokenStore.getAccessToken(authentication);
 5         OAuth2RefreshToken refreshToken = null;
 6         if (existingAccessToken != null) {
 7             if (existingAccessToken.isExpired()) {
 8                 if (existingAccessToken.getRefreshToken() != null) {
 9                     refreshToken = existingAccessToken.getRefreshToken();
10                     // The token store could remove the refresh token when the
11                     // access token is removed, but we want to
12                     // be sure...
13                     tokenStore.removeRefreshToken(refreshToken);
14                 }
15                 tokenStore.removeAccessToken(existingAccessToken);
16             }
17             else {
18                 // Re-store the access token in case the authentication has changed
19                 tokenStore.storeAccessToken(existingAccessToken, authentication);
20                 return existingAccessToken;
21             }
22         }
23 
24         // Only create a new refresh token if there wasn't an existing one
25         // associated with an expired access token.
26         // Clients might be holding existing refresh tokens, so we re-use it in
27         // the case that the old access token
28         // expired.
29         if (refreshToken == null) {
30             refreshToken = createRefreshToken(authentication);
31         }
32         // But the refresh token itself might need to be re-issued if it has
33         // expired.
34         else if (refreshToken instanceof ExpiringOAuth2RefreshToken) {
35             ExpiringOAuth2RefreshToken expiring = (ExpiringOAuth2RefreshToken) refreshToken;
36             if (System.currentTimeMillis() > expiring.getExpiration().getTime()) {
37                 refreshToken = createRefreshToken(authentication);
38             }
39         }
40 
41         OAuth2AccessToken accessToken = createAccessToken(authentication, refreshToken);
42         tokenStore.storeAccessToken(accessToken, authentication);
43         // In case it was modified
44         refreshToken = accessToken.getRefreshToken();
45         if (refreshToken != null) {
46             tokenStore.storeRefreshToken(refreshToken, authentication);
47         }
48         return accessToken;
49 
50     }

Our project uses redis storage token, if there is not expired token, return 20 rows directly behind the code is on refreshToken has expired, expired refresh process accessToken and refreshToken created, the default is UUID.randomUUID (). ToString () generates a UUID, the time has expired mechanisms, and finally deposit
tokenStore, for our project tokenStore is redis. 

This token acquisition process analysis is completed.




Third, requested authentication and authorization process analysis

when the client application requests a child, you need to go first to an authentication server authentication, authorization server to detect and then to authority, how to do it? Suppose for the service application A, here two service authentication and authorization is done in one of, let's call it B;

authentication and authorization process diagram is as follows,

 
















































































  

Guess you like

Origin www.cnblogs.com/mylittlecabin/p/11420283.html