Demo见spring security 官网 spring-projects/spring-security-samples at 5.6.x (github.com)
![](https://img2022.cnblogs.com/blog/1192718/202202/1192718-20220211171012084-514162272.png)
登录服务器 localhost:8080 认证服务器 localhost:9000 ############################################################################################################# localhost:8080 FilterSecurityInterceptor AbstractSecurityInterceptor.attemptAuthorization AffirmativeBased.decide throw new AccessDeniedException ExceptionTranslationFilter handleSpringSecurityException(request, response, chain, securityException); handleAccessDeniedException sendStartAuthentication(request, response, chain, this.requestCache.saveRequest(request, response); request.getSession().setAttribute("SPRING_SECURITY_SAVED_REQUEST", savedRequest); 保存请求localhost:8080 LoginUrlAuthenticationEntryPoint.commence DefaultRedirectStrategy.sendRedirect http://127.0.0.1:8080/login GET http://127.0.0.1:8080/login GET DefaultLoginPageGeneratingFilter 生成客户端登录页面 点击Spring http://127.0.0.1:8080/oauth2/authorization/login-client GET http://127.0.0.1:8080/oauth2/authorization/login-client GET OAuth2AuthorizationRequestRedirectFilter DefaultOAuth2AuthorizationRequestResolver.resolve 默认/login sendRedirectForAuthorization http://localhost:9000/oauth2/authorize GET http://localhost:9000/oauth2/authorize GET FilterSecurityInterceptor super.beforeInvocation(filterInvocation); AbstractSecurityInterceptor.attemptAuthorization DefaultFilterInvocationSecurityMetadataSource.getAttributes authenticateIfRequired() AffirmativeBased.decide(authenticated, object, attributes) false voter.vote(authentication, object, configAttributes) throw new AccessDeniedException ExceptionTranslationFilter handleSpringSecurityException(request, response, chain, securityException); handleAccessDeniedException(request, response, chain, (AccessDeniedException) exception); sendStartAuthentication(request, response, chain, this.requestCache.saveRequest(request, response); DelegatingAuthenticationEntryPoint.commence(request, response, reason); /oauth2/token POST /oauth2/introspect POST /oauth2/revoke POST Not Header X-Requested-With XMLHttpRequest application/xhtml+xml image/* text/html text/plain LoginUrlAuthenticationEntryPoint.commence response.sendRedirect(redirectUrl); http://localhost:9000/login GET http://localhost:9000/login GET DefaultLoginPageGeneratingFilter 生成认证页面 点击登录 http://localhost:9000/login POST UsernamePasswordAuthenticationFilter extend AbstractAuthenticationProcessingFilter DaoAuthenticationProvider.authenticate(authentication) this.getUserDetailsService().loadUserByUsername(username); additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication) DelegatingPasswordEncoder.matches BCrypt.checkpw(rawPassword.toString(), encodedPassword) this.postAuthenticationChecks.check(user) 过期检查 缓存 successfulAuthentication(request, response, chain, authenticationResult); SavedRequestAwareAuthenticationSuccessHandler.onAuthenticationSuccess(request, response, authResult) DefaultRedirectStrategy.sendRedirect http://localhost:9000/oauth2/authorize?response_type=code&client_id=login-client&scope=openid%20profile&state=K5AljHvfBD-D6lNDIYwZH5Xpt-bpf1wBR4D7RLu30d4%3D&redirect_uri=http://127.0.0.1:8080/login/oauth2/code/login-client&nonce=RjZiXvbR831dYaUeWaTRhhpFBtfQWM-DX4E82tiv27E http://localhost:9000/oauth2/authorize OAuth2AuthorizationEndpointFilter OAuth2AuthorizationCodeRequestAuthenticationProvider.authenticateAuthorizationRequest sendAuthorizationConsent DefaultConsentPage.displayConsent(request, response, clientId, principal, requestedScopes, authorizedScopes, state); response.getWriter().write(consentPage); 授权页面 点击同意授权 http://localhost:9000/oauth2/authorize POST OAuth2AuthorizationEndpointFilter OAuth2AuthorizationCodeRequestAuthenticationProvider.authenticateAuthorizationConsent authenticateAuthorizationRequest(authentication) 生成code this.authenticationSuccessHandler.onAuthenticationSuccess( this::sendAuthorizationResponse sendRedirect http://127.0.0.1:8080/login/oauth2/code/login-client?code=jvuAwiH1Hcioum87t96jUgy5zTJBaIHSyAK5ostooztCzVQcq_29s-uw7DXO0YVL-JwPrGYjEWImJGbUACEze5ndn_Tysh9X7fXt_lHGVp7eQEEG9lUkC5M5_jQ58k10&state=WWadeKiDpHU_afqlz9gl6PSJ8YLrSzLqXXuJKa8v6jw%3D http://127.0.0.1:8080/login/oauth2/code/login-client GET OAuth2LoginAuthenticationFilter this.getAuthenticationManager().authenticate(authenticationRequest); OAuth2LoginAuthenticationProvider.authenticate OidcAuthorizationCodeAuthenticationProvider.authenticate DefaultAuthorizationCodeTokenResponseClient.getTokenResponse this.restOperations.exchange(request, OAuth2AccessTokenResponse.class) http://localhost:9000/oauth2/token POST createOidcToken(clientRegistration, accessTokenResponse); getJwt(accessTokenResponse, jwtDecoder); NimbusJwtDecoder.decode((String) parameters.get(OidcParameterNames.ID_TOKEN)); createJwt(token, jwt) DefaultJWTProcessor.process(parsedJwt, null); selectKeys(signedJWT.getHeader(), claimsSet, context); etJWSKeySelector().selectJWSKeys(header, context); JWSVerificationKeySelector.getJWKSource().get(new JWKSelector(jwkMatcher), context); RemoteJWKSet.updateJWKSetFromURL(); jwkSetRetriever.retrieveResource(jwkSetURL) this.restOperations.exchange(request, String.class); http://localhost:9000/oauth2/jwks NimbusJwkSetEndpointFilter jwkSet = new JWKSet(this.jwkSource.get(this.jwkSelector, null)) writer.write(jwkSet.toString()); SavedRequestAwareAuthenticationSuccessHandler.onAuthenticationSuccess DefaultRedirectStrategy.sendRedirect 从session中取出之前保存的请求并转发 SPRING_SECURITY_SAVED_REQUEST http://127.0.0.1:8080/ ------------------------------------------------------------------------------------------------------------ http://localhost:9000/oauth2/token POST OAuth2ClientAuthenticationFilter OAuth2ClientAuthenticationProvider.authenticate(authenticationRequest) this.authenticationSuccessHandler.onAuthenticationSuccess(request, response, authenticationResult); OAuth2TokenEndpointFilter OAuth2AuthorizationCodeAuthenticationProvider.authenticate throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_GRANT); this::sendErrorResponse.onAuthenticationFailure(request, response, ex) writeInternal(t, outputMessage); outputMessage.getBody().flush(); this::sendAccessTokenResponse onAuthenticationSuccess 写token http://localhost:9000/oauth2/jwks GET NimbusJwkSetEndpointFilter new JWKSet(this.jwkSource.get(this.jwkSelector, null)); writer.write(jwkSet.toString()) ############################################################################################################# session SPRING_SECURITY_SAVED_REQUEST --> http://127.0.0.1:8080/
开始访问首页 localhost:8080
跳转到登录页面 http://127.0.0.1:8080/login
![](https://img2022.cnblogs.com/blog/1192718/202202/1192718-20220211165714166-2046932952.png)
点击spring
跳转到授权服务器的登录页面 http://localhost:9000/login
点击 Sign in
跳转到授权页面 http://localhost:9000/oauth2/authorize
勾选profile 并点击 Submit Consent
返回首页 localhost:8080
![](https://img2022.cnblogs.com/blog/1192718/202202/1192718-20220211165615544-1942432957.png)
相互学习,共同进步!