spring security oauth2 使用说明


spring security oauth2 使用说明

 

spring security oauth2实现了oauth2协议,可搭建client(客户端)resource server(资源服务器)authorization server(认证服务器)

其中client(客户端)可用来实现三方登陆,spring-security-oauth2-client默认集成了githubgooglefacebookokta,也提供了一些接口,可实现支付宝qq微信等三方授权登录

 

 

**************************

相关 jar 包

 

        
            org.springframework.boot
            spring-boot-starter-security
            2.2.6.RELEASE
        

        
            org.springframework.security
            spring-security-oauth2-client
            5.3.1.RELEASE
        

 

 

**************************

配置类

 

OAuth2ClientAutoConfiguration:客户端自动配置类

@Configuration(
    proxyBeanMethods = false
)
@AutoConfigureBefore({SecurityAutoConfiguration.class})
@ConditionalOnClass({EnableWebSecurity.class, ClientRegistration.class})
@ConditionalOnWebApplication(
    type = Type.SERVLET
)
@Import({OAuth2ClientRegistrationRepositoryConfiguration.class, OAuth2WebSecurityConfiguration.class})
public class OAuth2ClientAutoConfiguration {
    public OAuth2ClientAutoConfiguration() {
    }
}

说明:该自动配置类导入OAuth2ClientRegistrationRepositoryConfigurationOAuth2WebSecurityConfiguration

 

 

OAuth2ClientRegistrationRepositoryConfiguration:客户端配置类

@Configuration(
    proxyBeanMethods = false
)
@EnableConfigurationProperties({OAuth2ClientProperties.class})
@Conditional({ClientsConfiguredCondition.class})
class OAuth2ClientRegistrationRepositoryConfiguration {
    OAuth2ClientRegistrationRepositoryConfiguration() {
    }

    @Bean
    @ConditionalOnMissingBean({ClientRegistrationRepository.class})
    InMemoryClientRegistrationRepository clientRegistrationRepository(OAuth2ClientProperties properties) {
        List registrations = new ArrayList(OAuth2ClientPropertiesRegistrationAdapter.getClientRegistrations(properties).values());
        return new InMemoryClientRegistrationRepository(registrations);
    }//如果不存在ClientRegistrationRepository实例,则创建InMemoryClientRegistrationRepository实例
}

 

OAuth2ClientProperties:自动配置属性

@ConfigurationProperties(
    prefix = "spring.security.oauth2.client"
)
public class OAuth2ClientProperties {
    private final Map provider = new HashMap();
    private final Map registration = new HashMap();


*****************
内部类

    public static class Provider {
        private String authorizationUri;
        private String tokenUri;
        private String userInfoUri;
        private String userInfoAuthenticationMethod;
        private String userNameAttribute;
        private String jwkSetUri;
        private String issuerUri;


*****************
内部类

    public static class Registration {
        private String provider;
        private String clientId;
        private String clientSecret;
        private String clientAuthenticationMethod;
        private String authorizationGrantType;
        private String redirectUri;
        private Set scope;
        private String clientName;

 

ClientRegistrationRepository:根据registrationId查找ClientRegistration类

public interface ClientRegistrationRepository {
    ClientRegistration findByRegistrationId(String var1);
}

 

InMemoryClientRegistrationRepository:保存客户端配置

public final class InMemoryClientRegistrationRepository implements ClientRegistrationRepository, Iterable {
    private final Map registrations;

    public InMemoryClientRegistrationRepository(ClientRegistration... registrations) {
        this(Arrays.asList(registrations));
    }

    public InMemoryClientRegistrationRepository(List registrations) {
        this(createRegistrationsMap(registrations));
    }

    private static Map createRegistrationsMap(List registrations) {
        Assert.notEmpty(registrations, "registrations cannot be empty");
        return toUnmodifiableConcurrentMap(registrations);
    }

    private static Map toUnmodifiableConcurrentMap(List registrations) {
        ConcurrentHashMap result = new ConcurrentHashMap();
        Iterator var2 = registrations.iterator();

        while(var2.hasNext()) {
            ClientRegistration registration = (ClientRegistration)var2.next();
            if (result.containsKey(registration.getRegistrationId())) {
                throw new IllegalStateException(String.format("Duplicate key %s", registration.getRegistrationId()));
            }

            result.put(registration.getRegistrationId(), registration);
        }

        return Collections.unmodifiableMap(result);
    }

    public InMemoryClientRegistrationRepository(Map registrations) {
        Assert.notNull(registrations, "registrations cannot be null");
        this.registrations = registrations;
    }

    public ClientRegistration findByRegistrationId(String registrationId) {
        Assert.hasText(registrationId, "registrationId cannot be empty");
        return (ClientRegistration)this.registrations.get(registrationId);
    }

    public Iterator iterator() {
        return this.registrations.values().iterator();
    }
}

 

 

OAuth2WebSecurityConfiguration:oauth2客户端安全配置

@Configuration(
    proxyBeanMethods = false
)
@ConditionalOnBean({ClientRegistrationRepository.class})
class OAuth2WebSecurityConfiguration {
    OAuth2WebSecurityConfiguration() {
    }

    @Bean
    @ConditionalOnMissingBean
    OAuth2AuthorizedClientService authorizedClientService(ClientRegistrationRepository clientRegistrationRepository) {
        return new InMemoryOAuth2AuthorizedClientService(clientRegistrationRepository);
    }//不存在 OAuth2AuthorizedClientService,则创建该类

    @Bean
    @ConditionalOnMissingBean
    OAuth2AuthorizedClientRepository authorizedClientRepository(OAuth2AuthorizedClientService authorizedClientService) {
        return new AuthenticatedPrincipalOAuth2AuthorizedClientRepository(authorizedClientService);
    }//不存在授权客户端,则创建AuthenticatedPrincipalOAuth2AuthorizedClientRepository

    @Configuration(
        proxyBeanMethods = false
    )
    @ConditionalOnMissingBean({WebSecurityConfigurerAdapter.class})
    static class OAuth2WebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
        OAuth2WebSecurityConfigurerAdapter() {
        }

        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests((requests) -> {
                ((AuthorizedUrl)requests.anyRequest()).authenticated();
            });
            http.oauth2Login(Customizer.withDefaults());
            http.oauth2Client();
        }//配置默认的安全策略
    }
}

 

OAuth2AuthorizedClientService:授权客户端操作接口

public interface OAuth2AuthorizedClientService {
     T loadAuthorizedClient(String var1, String var2);  //加载授权客户端

    void saveAuthorizedClient(OAuth2AuthorizedClient var1, Authentication var2);          //保存授权客户端

    void removeAuthorizedClient(String var1, String var2);                                //删除授权客户端
}

 

InMemoryOAuth2AuthorizedClientService:授权客户端操作类

public final class InMemoryOAuth2AuthorizedClientService implements OAuth2AuthorizedClientService {
    private final Map authorizedClients;   //保存授权客户端
    private final ClientRegistrationRepository clientRegistrationRepository;

    public InMemoryOAuth2AuthorizedClientService(ClientRegistrationRepository clientRegistrationRepository) {
        Assert.notNull(clientRegistrationRepository, "clientRegistrationRepository cannot be null");
        this.clientRegistrationRepository = clientRegistrationRepository;
        this.authorizedClients = new ConcurrentHashMap();
    }

    public InMemoryOAuth2AuthorizedClientService(ClientRegistrationRepository clientRegistrationRepository, Map authorizedClients) {
        Assert.notNull(clientRegistrationRepository, "clientRegistrationRepository cannot be null");
        Assert.notEmpty(authorizedClients, "authorizedClients cannot be empty");
        this.clientRegistrationRepository = clientRegistrationRepository;
        this.authorizedClients = new ConcurrentHashMap(authorizedClients);
    }

    public  T loadAuthorizedClient(String clientRegistrationId, String principalName) {
        Assert.hasText(clientRegistrationId, "clientRegistrationId cannot be empty");
        Assert.hasText(principalName, "principalName cannot be empty");
        ClientRegistration registration = this.clientRegistrationRepository.findByRegistrationId(clientRegistrationId);
        return registration == null ? null : (OAuth2AuthorizedClient)this.authorizedClients.get(new OAuth2AuthorizedClientId(clientRegistrationId, principalName));
    }

    public void saveAuthorizedClient(OAuth2AuthorizedClient authorizedClient, Authentication principal) {
        Assert.notNull(authorizedClient, "authorizedClient cannot be null");
        Assert.notNull(principal, "principal cannot be null");
        this.authorizedClients.put(new OAuth2AuthorizedClientId(authorizedClient.getClientRegistration().getRegistrationId(), principal.getName()), authorizedClient);
    }

    public void removeAuthorizedClient(String clientRegistrationId, String principalName) {
        Assert.hasText(clientRegistrationId, "clientRegistrationId cannot be empty");
        Assert.hasText(principalName, "principalName cannot be empty");
        ClientRegistration registration = this.clientRegistrationRepository.findByRegistrationId(clientRegistrationId);
        if (registration != null) {
            this.authorizedClients.remove(new OAuth2AuthorizedClientId(clientRegistrationId, principalName));
        }

    }
}

 

OAuth2AuthorizedClientId:Map authorizedClients中的key

public final class OAuth2AuthorizedClientId implements Serializable {
    private static final long serialVersionUID = 530L;
    private final String clientRegistrationId;
    private final String principalName;

    public OAuth2AuthorizedClientId(String clientRegistrationId, String principalName) {

    public boolean equals(Object obj) {
    public int hashCode() {

 

OAuth2AuthorizedClient:oauth2授权客户端

public class OAuth2AuthorizedClient implements Serializable {
    private static final long serialVersionUID = 530L;
    private final ClientRegistration clientRegistration;
    private final String principalName;
    private final OAuth2AccessToken accessToken;
    private final OAuth2RefreshToken refreshToken;

    public OAuth2AuthorizedClient(ClientRegistration clientRegistration, String principalName, OAuth2AccessToken accessToken) {
    public OAuth2AuthorizedClient(ClientRegistration clientRegistration, String principalName, OAuth2AccessToken accessToken, @Nullable OAuth2RefreshToken refreshToken) {

    public ClientRegistration getClientRegistration() {    //获取客户端配置类
    public String getPrincipalName() {                     //获取认证用户名称
    public OAuth2AccessToken getAccessToken() {            //获取access token

    @Nullable
    public OAuth2RefreshToken getRefreshToken() {

 

ClientRegistration:客户端类

public final class ClientRegistration implements Serializable {
    private static final long serialVersionUID = 530L;
    private String registrationId;
    private String clientId;
    private String clientSecret;
    private ClientAuthenticationMethod clientAuthenticationMethod;
    private AuthorizationGrantType authorizationGrantType;
    private String redirectUriTemplate;
    private Set scopes;
    private ClientRegistration.ProviderDetails providerDetails;
    private String clientName;

    private ClientRegistration() {
        this.clientAuthenticationMethod = ClientAuthenticationMethod.BASIC;
        this.scopes = Collections.emptySet();
        this.providerDetails = new ClientRegistration.ProviderDetails();
    }


    public String getRegistrationId() {
    public String getClientId() {
    public String getClientSecret() {
    public ClientAuthenticationMethod getClientAuthenticationMethod() {
    public AuthorizationGrantType getAuthorizationGrantType() {
    public String getRedirectUriTemplate() {
    public Set getScopes() {
    public ClientRegistration.ProviderDetails getProviderDetails() {
    public String getClientName() {
    public String toString() {

    public static ClientRegistration.Builder withRegistrationId(String registrationId) {
        Assert.hasText(registrationId, "registrationId cannot be empty");
        return new ClientRegistration.Builder(registrationId);
    }

    public static ClientRegistration.Builder withClientRegistration(ClientRegistration clientRegistration) {
        Assert.notNull(clientRegistration, "clientRegistration cannot be null");
        return new ClientRegistration.Builder(clientRegistration);
    }



*****************
内部类:ClientRegistration.Builder

    public static class Builder implements Serializable {
        private static final long serialVersionUID = 530L;
        private String registrationId;
        private String clientId;
        private String clientSecret;
        private ClientAuthenticationMethod clientAuthenticationMethod;
        private AuthorizationGrantType authorizationGrantType;
        private String redirectUriTemplate;
        private Set scopes;
        private String authorizationUri;
        private String tokenUri;
        private String userInfoUri;
        private AuthenticationMethod userInfoAuthenticationMethod;
        private String userNameAttributeName;
        private String jwkSetUri;
        private Map configurationMetadata;
        private String clientName;

        private Builder(String registrationId) {
            this.clientAuthenticationMethod = ClientAuthenticationMethod.BASIC;
            this.userInfoAuthenticationMethod = AuthenticationMethod.HEADER;
            this.configurationMetadata = Collections.emptyMap();
            this.registrationId = registrationId;
        }

        private Builder(ClientRegistration clientRegistration) {

        public ClientRegistration.Builder registrationId(String registrationId) {
        public ClientRegistration.Builder clientId(String clientId) {
        public ClientRegistration.Builder clientSecret(String clientSecret) {
        public ClientRegistration.Builder clientAuthenticationMethod(ClientAuthenticationMethod clientAuthenticationMethod) {
        public ClientRegistration.Builder authorizationGrantType(AuthorizationGrantType authorizationGrantType) {
        public ClientRegistration.Builder redirectUriTemplate(String redirectUriTemplate) {

        public ClientRegistration.Builder scope(String... scope) {
        public ClientRegistration.Builder scope(Collection scope) {

        public ClientRegistration.Builder authorizationUri(String authorizationUri) {
        public ClientRegistration.Builder tokenUri(String tokenUri) {
        public ClientRegistration.Builder userInfoUri(String userInfoUri) {
        public ClientRegistration.Builder userInfoAuthenticationMethod(AuthenticationMethod userInfoAuthenticationMethod) {
        public ClientRegistration.Builder userNameAttributeName(String userNameAttributeName) {
        public ClientRegistration.Builder jwkSetUri(String jwkSetUri) {

        public ClientRegistration.Builder providerConfigurationMetadata(Map configurationMetadata) {
        public ClientRegistration.Builder clientName(String clientName) {

        public ClientRegistration build() {

        private ClientRegistration create() {
        private void validateAuthorizationCodeGrantType() {
        private void validateImplicitGrantType() {
        private void validatePasswordGrantType() {
        private void validateScopes() {
        private static boolean validateScope(String scope) {



*****************
内部类:ClientRegistration.ProviderDetails


    public class ProviderDetails implements Serializable {
        private static final long serialVersionUID = 530L;
        private String authorizationUri;
        private String tokenUri;
        private ClientRegistration.ProviderDetails.UserInfoEndpoint userInfoEndpoint;
        private String jwkSetUri;
        private Map configurationMetadata;

        private ProviderDetails() {
            this.userInfoEndpoint = new ClientRegistration.ProviderDetails.UserInfoEndpoint();
            this.configurationMetadata = Collections.emptyMap();
        }

        public String getAuthorizationUri() {
        public String getTokenUri() {

        public ClientRegistration.ProviderDetails.UserInfoEndpoint getUserInfoEndpoint() {
        public String getJwkSetUri() {
        public Map getConfigurationMetadata() {



*****************
内部类:ClientRegistration.ProviderDetails.UserInfoEndpoint

        public class UserInfoEndpoint implements Serializable {
            private static final long serialVersionUID = 530L;
            private String uri;
            private AuthenticationMethod authenticationMethod;
            private String userNameAttributeName;

            private UserInfoEndpoint() {
                this.authenticationMethod = AuthenticationMethod.HEADER;
            }

            public String getUri() {
            public AuthenticationMethod getAuthenticationMethod() {
            public String getUserNameAttributeName() {

 

 

OAuth2AuthorizedClientRepository:授权客户端操作接口

public interface OAuth2AuthorizedClientRepository {
     T loadAuthorizedClient(String var1, Authentication var2, HttpServletRequest var3);

    void saveAuthorizedClient(OAuth2AuthorizedClient var1, Authentication var2, HttpServletRequest var3, HttpServletResponse var4);

    void removeAuthorizedClient(String var1, Authentication var2, HttpServletRequest var3, HttpServletResponse var4);
}

 

AuthenticatedPrincipalOAuth2AuthorizedClientRepository:OAuth2AuthorizedClientRepository接口实现类

public final class AuthenticatedPrincipalOAuth2AuthorizedClientRepository implements OAuth2AuthorizedClientRepository {
    private final AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl();
    private final OAuth2AuthorizedClientService authorizedClientService;
                                                //内部调用authorizedClientService方法
    private OAuth2AuthorizedClientRepository anonymousAuthorizedClientRepository = new HttpSessionOAuth2AuthorizedClientRepository();

    public AuthenticatedPrincipalOAuth2AuthorizedClientRepository(OAuth2AuthorizedClientService authorizedClientService) {
        Assert.notNull(authorizedClientService, "authorizedClientService cannot be null");
        this.authorizedClientService = authorizedClientService;
    }

    public void setAnonymousAuthorizedClientRepository(OAuth2AuthorizedClientRepository anonymousAuthorizedClientRepository) {
        Assert.notNull(anonymousAuthorizedClientRepository, "anonymousAuthorizedClientRepository cannot be null");
        this.anonymousAuthorizedClientRepository = anonymousAuthorizedClientRepository;
    }

    public  T loadAuthorizedClient(String clientRegistrationId, Authentication principal, HttpServletRequest request) {
        return this.isPrincipalAuthenticated(principal) ? this.authorizedClientService.loadAuthorizedClient(clientRegistrationId, principal.getName()) : this.anonymousAuthorizedClientRepository.loadAuthorizedClient(clientRegistrationId, principal, request);
                 //通过认证后,调用authotizedClientService的loadAuthorizedClient加载授权客户端
    }

    public void saveAuthorizedClient(OAuth2AuthorizedClient authorizedClient, Authentication principal, HttpServletRequest request, HttpServletResponse response) {
        if (this.isPrincipalAuthenticated(principal)) {
            this.authorizedClientService.saveAuthorizedClient(authorizedClient, principal);
                 //通过认证后,调用authoriedClientService的saveAuthorizedClient保存授权客户端
        } else {
            this.anonymousAuthorizedClientRepository.saveAuthorizedClient(authorizedClient, principal, request, response);
        }

    }

    public void removeAuthorizedClient(String clientRegistrationId, Authentication principal, HttpServletRequest request, HttpServletResponse response) {
        if (this.isPrincipalAuthenticated(principal)) {
            this.authorizedClientService.removeAuthorizedClient(clientRegistrationId, principal.getName());
                 //通过认证后,调用authoriedClientService的removeAuthorizedClient删除授权客户端
        } else {
            this.anonymousAuthorizedClientRepository.removeAuthorizedClient(clientRegistrationId, principal, request, response);
        }

    }

    private boolean isPrincipalAuthenticated(Authentication authentication) {
        return authentication != null && !this.authenticationTrustResolver.isAnonymous(authentication) && authentication.isAuthenticated();
    }
}

 

CommonOAuth2Provider:默认提供的三方客户端配置,google、github、facebook、okta

public enum CommonOAuth2Provider {
    GOOGLE {
        public Builder getBuilder(String registrationId) {
            Builder builder = this.getBuilder(registrationId, ClientAuthenticationMethod.BASIC, "{baseUrl}/{action}/oauth2/code/{registrationId}");
            builder.scope(new String[]{"openid", "profile", "email"});
            builder.authorizationUri("https://accounts.google.com/o/oauth2/v2/auth");
            builder.tokenUri("https://www.googleapis.com/oauth2/v4/token");
            builder.jwkSetUri("https://www.googleapis.com/oauth2/v3/certs");
            builder.userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo");
            builder.userNameAttributeName("sub");
            builder.clientName("Google");
            return builder;
        }
    },
    GITHUB {
        public Builder getBuilder(String registrationId) {
            Builder builder = this.getBuilder(registrationId, ClientAuthenticationMethod.BASIC, "{baseUrl}/{action}/oauth2/code/{registrationId}");
            builder.scope(new String[]{"read:user"});
            builder.authorizationUri("https://github.com/login/oauth/authorize");
            builder.tokenUri("https://github.com/login/oauth/access_token");
            builder.userInfoUri("https://api.github.com/user");
            builder.userNameAttributeName("id");
            builder.clientName("GitHub");
            return builder;
        }
    },
    FACEBOOK {
        public Builder getBuilder(String registrationId) {
            Builder builder = this.getBuilder(registrationId, ClientAuthenticationMethod.POST, "{baseUrl}/{action}/oauth2/code/{registrationId}");
            builder.scope(new String[]{"public_profile", "email"});
            builder.authorizationUri("https://www.facebook.com/v2.8/dialog/oauth");
            builder.tokenUri("https://graph.facebook.com/v2.8/oauth/access_token");
            builder.userInfoUri("https://graph.facebook.com/me?fields=id,name,email");
            builder.userNameAttributeName("id");
            builder.clientName("Facebook");
            return builder;
        }
    },
    OKTA {
        public Builder getBuilder(String registrationId) {
            Builder builder = this.getBuilder(registrationId, ClientAuthenticationMethod.BASIC, "{baseUrl}/{action}/oauth2/code/{registrationId}");
            builder.scope(new String[]{"openid", "profile", "email"});
            builder.userNameAttributeName("sub");
            builder.clientName("Okta");
            return builder;
        }
    };

    private static final String DEFAULT_REDIRECT_URL = "{baseUrl}/{action}/oauth2/code/{registrationId}";

    private CommonOAuth2Provider() {
    }

    protected final Builder getBuilder(String registrationId, ClientAuthenticationMethod method, String redirectUri) {
        Builder builder = ClientRegistration.withRegistrationId(registrationId);
        builder.clientAuthenticationMethod(method);
        builder.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE);
        builder.redirectUriTemplate(redirectUri);
        return builder;
    }

    public abstract Builder getBuilder(String var1);
}

 

 

**************************

安全配置类

 

HttpSecurity:安全配置

public final class HttpSecurity extends AbstractConfiguredSecurityBuilder implements SecurityBuilder, HttpSecurityBuilder {

***************
OAuth2Login 相关配置

    public OAuth2LoginConfigurer oauth2Login() throws Exception {
        return (OAuth2LoginConfigurer)this.getOrApply(new OAuth2LoginConfigurer());
    }

    public HttpSecurity oauth2Login(Customizer> oauth2LoginCustomizer) throws Exception {
        oauth2LoginCustomizer.customize(this.getOrApply(new OAuth2LoginConfigurer()));
        return this;
    }

 

OAuth2LoginConfigurer

public final class OAuth2LoginConfigurer> extends AbstractAuthenticationFilterConfigurer, OAuth2LoginAuthenticationFilter> {
    private final OAuth2LoginConfigurer.AuthorizationEndpointConfig authorizationEndpointConfig = new OAuth2LoginConfigurer.AuthorizationEndpointConfig();
    private final OAuth2LoginConfigurer.TokenEndpointConfig tokenEndpointConfig = new OAuth2LoginConfigurer.TokenEndpointConfig();
    private final OAuth2LoginConfigurer.RedirectionEndpointConfig redirectionEndpointConfig = new OAuth2LoginConfigurer.RedirectionEndpointConfig();
    private final OAuth2LoginConfigurer.UserInfoEndpointConfig userInfoEndpointConfig = new OAuth2LoginConfigurer.UserInfoEndpointConfig();
    private String loginPage;
    private String loginProcessingUrl = "/login/oauth2/code/*";  //获得授权码code后的回调路径

    public OAuth2LoginConfigurer() {
    }

    public OAuth2LoginConfigurer clientRegistrationRepository(ClientRegistrationRepository clientRegistrationRepository) {
    public OAuth2LoginConfigurer authorizedClientRepository(OAuth2AuthorizedClientRepository authorizedClientRepository) {
    public OAuth2LoginConfigurer authorizedClientService(OAuth2AuthorizedClientService authorizedClientService) {


    public OAuth2LoginConfigurer loginPage(String loginPage) {
    public OAuth2LoginConfigurer loginProcessingUrl(String loginProcessingUrl) {


*************
authorizationEndpoint:请求获取授权码相关操作

    public OAuth2LoginConfigurer.AuthorizationEndpointConfig authorizationEndpoint() {
    public OAuth2LoginConfigurer authorizationEndpoint(Customizer.AuthorizationEndpointConfig> authorizationEndpointCustomizer) {


*************
tokenEndpoint:token相关操作

    public OAuth2LoginConfigurer.TokenEndpointConfig tokenEndpoint() {
    public OAuth2LoginConfigurer tokenEndpoint(Customizer.TokenEndpointConfig> tokenEndpointCustomizer) {


*************
redirectionEndpoint:获取授权码code后的回调操作

    public OAuth2LoginConfigurer.RedirectionEndpointConfig redirectionEndpoint() {
    public OAuth2LoginConfigurer redirectionEndpoint(Customizer.RedirectionEndpointConfig> redirectionEndpointCustomizer) {


*************
userInfoEndpoint:用户信息操作(用户权限、自定义用户类)

    public OAuth2LoginConfigurer.UserInfoEndpointConfig userInfoEndpoint() {
    public OAuth2LoginConfigurer userInfoEndpoint(Customizer.UserInfoEndpointConfig> userInfoEndpointCustomizer) {



    public void init(B http) throws Exception {            //初始化操作
        OAuth2LoginAuthenticationFilter authenticationFilter = new OAuth2LoginAuthenticationFilter(OAuth2ClientConfigurerUtils.getClientRegistrationRepository((HttpSecurityBuilder)this.getBuilder()), OAuth2ClientConfigurerUtils.getAuthorizedClientRepository((HttpSecurityBuilder)this.getBuilder()), this.loginProcessingUrl);
        this.setAuthenticationFilter(authenticationFilter);    //设置登录认证过滤器
        super.loginProcessingUrl(this.loginProcessingUrl);     //设置登陆处理路径,默认为:/login/oauth2/code/*

        if (this.loginPage != null) {
            super.loginPage(this.loginPage);
            super.init(http);
        } else {
            Map loginUrlToClientName = this.getLoginLinks();
            if (loginUrlToClientName.size() == 1) {
                this.updateAuthenticationDefaults();
                this.updateAccessDefaults(http);
                String providerLoginPage = (String)loginUrlToClientName.keySet().iterator().next();
                this.registerAuthenticationEntryPoint(http, this.getLoginEntryPoint(http, providerLoginPage));
            } else {
                super.init(http);
            }
        }    //登陆页面路径设置,默认为:/login

        OAuth2AccessTokenResponseClient accessTokenResponseClient = this.tokenEndpointConfig.accessTokenResponseClient;
        if (accessTokenResponseClient == null) {
            accessTokenResponseClient = new DefaultAuthorizationCodeTokenResponseClient();
        }

        OAuth2UserService oauth2UserService = this.getOAuth2UserService();
        OAuth2LoginAuthenticationProvider oauth2LoginAuthenticationProvider = new OAuth2LoginAuthenticationProvider((OAuth2AccessTokenResponseClient)accessTokenResponseClient, oauth2UserService);
        GrantedAuthoritiesMapper userAuthoritiesMapper = this.getGrantedAuthoritiesMapper();
        if (userAuthoritiesMapper != null) {
            oauth2LoginAuthenticationProvider.setAuthoritiesMapper(userAuthoritiesMapper);
        }

        http.authenticationProvider((AuthenticationProvider)this.postProcess(oauth2LoginAuthenticationProvider));
        boolean oidcAuthenticationProviderEnabled = ClassUtils.isPresent("org.springframework.security.oauth2.jwt.JwtDecoder", this.getClass().getClassLoader());
        if (oidcAuthenticationProviderEnabled) {
            OAuth2UserService oidcUserService = this.getOidcUserService();
            OidcAuthorizationCodeAuthenticationProvider oidcAuthorizationCodeAuthenticationProvider = new OidcAuthorizationCodeAuthenticationProvider((OAuth2AccessTokenResponseClient)accessTokenResponseClient, oidcUserService);
            JwtDecoderFactory jwtDecoderFactory = this.getJwtDecoderFactoryBean();
            if (jwtDecoderFactory != null) {
                oidcAuthorizationCodeAuthenticationProvider.setJwtDecoderFactory(jwtDecoderFactory);
            }

            if (userAuthoritiesMapper != null) {
                oidcAuthorizationCodeAuthenticationProvider.setAuthoritiesMapper(userAuthoritiesMapper);
            }

            http.authenticationProvider((AuthenticationProvider)this.postProcess(oidcAuthorizationCodeAuthenticationProvider));
        } else {
            http.authenticationProvider(new OAuth2LoginConfigurer.OidcAuthenticationRequestChecker());
        }

        this.initDefaultLoginFilter(http);
    }

    public void configure(B http) throws Exception {
        OAuth2AuthorizationRequestRedirectFilter authorizationRequestFilter;
        if (this.authorizationEndpointConfig.authorizationRequestResolver != null) {
            authorizationRequestFilter = new OAuth2AuthorizationRequestRedirectFilter(this.authorizationEndpointConfig.authorizationRequestResolver);
        } else {
            String authorizationRequestBaseUri = this.authorizationEndpointConfig.authorizationRequestBaseUri;
            if (authorizationRequestBaseUri == null) {
                authorizationRequestBaseUri = "/oauth2/authorization";
            }

            authorizationRequestFilter = new OAuth2AuthorizationRequestRedirectFilter(OAuth2ClientConfigurerUtils.getClientRegistrationRepository((HttpSecurityBuilder)this.getBuilder()), authorizationRequestBaseUri);
        }

        if (this.authorizationEndpointConfig.authorizationRequestRepository != null) {
            authorizationRequestFilter.setAuthorizationRequestRepository(this.authorizationEndpointConfig.authorizationRequestRepository);
        }

        RequestCache requestCache = (RequestCache)http.getSharedObject(RequestCache.class);
        if (requestCache != null) {
            authorizationRequestFilter.setRequestCache(requestCache);
        }

        http.addFilter((Filter)this.postProcess(authorizationRequestFilter));
        OAuth2LoginAuthenticationFilter authenticationFilter = (OAuth2LoginAuthenticationFilter)this.getAuthenticationFilter();
        if (this.redirectionEndpointConfig.authorizationResponseBaseUri != null) {
            authenticationFilter.setFilterProcessesUrl(this.redirectionEndpointConfig.authorizationResponseBaseUri);
        }

        if (this.authorizationEndpointConfig.authorizationRequestRepository != null) {
            authenticationFilter.setAuthorizationRequestRepository(this.authorizationEndpointConfig.authorizationRequestRepository);
        }

        super.configure(http);
    }

    protected RequestMatcher createLoginProcessingUrlMatcher(String loginProcessingUrl) {

    private JwtDecoderFactory getJwtDecoderFactoryBean() {

    private GrantedAuthoritiesMapper getGrantedAuthoritiesMapper() {
    private GrantedAuthoritiesMapper getGrantedAuthoritiesMapperBean() {


    private OAuth2UserService getOidcUserService() {
                     //返回OidcUserService对象

        if (this.userInfoEndpointConfig.oidcUserService != null) {
            return this.userInfoEndpointConfig.oidcUserService;
        } else {
            ResolvableType type = ResolvableType.forClassWithGenerics(OAuth2UserService.class, new Class[]{OidcUserRequest.class, OidcUser.class});
            OAuth2UserService bean = (OAuth2UserService)this.getBeanOrNull(type);
            return (OAuth2UserService)(bean == null ? new OidcUserService() : bean);
        }
    }

    private OAuth2UserService getOAuth2UserService() {
        if (this.userInfoEndpointConfig.userService != null) {
                     //如果设置了userService,直接返回userService对象

            return this.userInfoEndpointConfig.userService;
        } else {
            ResolvableType type = ResolvableType.forClassWithGenerics(OAuth2UserService.class, new Class[]{OAuth2UserRequest.class, OAuth2User.class});
            OAuth2UserService bean = (OAuth2UserService)this.getBeanOrNull(type);
            if (bean == null) {
                if (!this.userInfoEndpointConfig.customUserTypes.isEmpty()) {
                     //如果userInfoEndpointConfig中customUserTypes不为空,返回代理对象DelegatingOAuth2UserService

                    List> userServices = new ArrayList();
                    userServices.add(new CustomUserTypesOAuth2UserService(this.userInfoEndpointConfig.customUserTypes));
                    userServices.add(new DefaultOAuth2UserService());
                    return new DelegatingOAuth2UserService(userServices);
                } else {
                     //如果为空,直接返回DefaultOAuth2UserService对象

                    return new DefaultOAuth2UserService();
                }
            } else {
                return bean;
            }
        }
    }

    private  T getBeanOrNull(ResolvableType type) {

    private void initDefaultLoginFilter(B http) {     //生成默认的登陆页面
        DefaultLoginPageGeneratingFilter loginPageGeneratingFilter = (DefaultLoginPageGeneratingFilter)http.getSharedObject(DefaultLoginPageGeneratingFilter.class);
        if (loginPageGeneratingFilter != null && !this.isCustomLoginPage()) {
            loginPageGeneratingFilter.setOauth2LoginEnabled(true);
            loginPageGeneratingFilter.setOauth2AuthenticationUrlToClientName(this.getLoginLinks());
            loginPageGeneratingFilter.setLoginPageUrl(this.getLoginPage());
            loginPageGeneratingFilter.setFailureUrl(this.getFailureUrl());
        }
    }

    private Map getLoginLinks() {     //授权认证的uri地址
        Iterable clientRegistrations = null;
        ClientRegistrationRepository clientRegistrationRepository = OAuth2ClientConfigurerUtils.getClientRegistrationRepository((HttpSecurityBuilder)this.getBuilder());
        ResolvableType type = ResolvableType.forInstance(clientRegistrationRepository).as(Iterable.class);
        if (type != ResolvableType.NONE && ClientRegistration.class.isAssignableFrom(type.resolveGenerics()[0])) {
            clientRegistrations = (Iterable)clientRegistrationRepository;
        }

        if (clientRegistrations == null) {
            return Collections.emptyMap();
        } else {
            String authorizationRequestBaseUri = this.authorizationEndpointConfig.authorizationRequestBaseUri != null ? this.authorizationEndpointConfig.authorizationRequestBaseUri : "/oauth2/authorization";
            Map loginUrlToClientName = new HashMap();
            clientRegistrations.forEach((registration) -> {
                String var10000 = (String)loginUrlToClientName.put(authorizationRequestBaseUri + "/" + registration.getRegistrationId(), registration.getClientName());
            });         //授权请求默认为:/oauth2/authorization + registration.getRegistrationId()

            return loginUrlToClientName;
        }
    }

    private AuthenticationEntryPoint getLoginEntryPoint(B http, String providerLoginPage) {



***************
内部类:OAuth2LoginConfigurer.OidcAuthenticationRequestChecker

    private static class OidcAuthenticationRequestChecker implements AuthenticationProvider {
        private OidcAuthenticationRequestChecker() {
        }

        public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        public boolean supports(Class authentication) {


***************
内部类:OAuth2LoginConfigurer.UserInfoEndpointConfig

    public class UserInfoEndpointConfig {
        private OAuth2UserService userService;
        private OAuth2UserService oidcUserService;
        private Map> customUserTypes;

        private UserInfoEndpointConfig() {
            this.customUserTypes = new HashMap();
        }

        public OAuth2LoginConfigurer.UserInfoEndpointConfig userService(OAuth2UserService userService) {
                               //设置OAuth2UserService,通过OAuth2UserRequest请求获取user

        public OAuth2LoginConfigurer.UserInfoEndpointConfig oidcUserService(OAuth2UserService oidcUserService) {
                               //设置OAuth2UserService,通过OidcUserRequest请求获取OidcUser

        public OAuth2LoginConfigurer.UserInfoEndpointConfig customUserType(Class customUserType, String clientRegistrationId) {
                               //设置用户类型OAuth2User

        public OAuth2LoginConfigurer.UserInfoEndpointConfig userAuthoritiesMapper(GrantedAuthoritiesMapper userAuthoritiesMapper) {
                               //设置用户权限

        public OAuth2LoginConfigurer and() {



***************
内部类:OAuth2LoginConfigurer.RedirectionEndpointConfig

    public class RedirectionEndpointConfig {
        private String authorizationResponseBaseUri;

        private RedirectionEndpointConfig() {
        }

        public OAuth2LoginConfigurer.RedirectionEndpointConfig baseUri(String authorizationResponseBaseUri) {
                              //获取授权码code后,回调的baseUri

        public OAuth2LoginConfigurer and() {



***************
内部类:OAuth2LoginConfigurer.TokenEndpointConfig

    public class TokenEndpointConfig {
        private OAuth2AccessTokenResponseClient accessTokenResponseClient;

        private TokenEndpointConfig() {
        }

        public OAuth2LoginConfigurer.TokenEndpointConfig accessTokenResponseClient(OAuth2AccessTokenResponseClient accessTokenResponseClient) {
                              //设置OAuth2AccessTokenResponseClient,通过该客户端获取token

        public OAuth2LoginConfigurer and() {


***************
内部类:OAuth2LoginConfigurer.AuthorizationEndpointConfig


    public class AuthorizationEndpointConfig {
        private String authorizationRequestBaseUri;
        private OAuth2AuthorizationRequestResolver authorizationRequestResolver;
        private AuthorizationRequestRepository authorizationRequestRepository;

        private AuthorizationEndpointConfig() {
        }

        public OAuth2LoginConfigurer.AuthorizationEndpointConfig baseUri(String authorizationRequestBaseUri) {
                             //设置授权请求的baseUri,如果不设置,默认为:/oauth2/authorization

        public OAuth2LoginConfigurer.AuthorizationEndpointConfig authorizationRequestResolver(OAuth2AuthorizationRequestResolver authorizationRequestResolver) {
                             //设置授权请求解析类,将HttpServletRequest转换为OAuth2AuthorizationRequest

        public OAuth2LoginConfigurer.AuthorizationEndpointConfig authorizationRequestRepository(AuthorizationRequestRepository authorizationRequestRepository) {
                             //设置授权请求操作类,加载、保存、删除授权请求

        public OAuth2LoginConfigurer and() {

 

UserService:加载用户

@FunctionalInterface
public interface OAuth2UserService {
    U loadUser(R var1) throws OAuth2AuthenticationException;
}

 

DefaultOAuth2UserService:默认的用户加载类

public class DefaultOAuth2UserService implements OAuth2UserService {
    private static final String MISSING_USER_INFO_URI_ERROR_CODE = "missing_user_info_uri";
    private static final String MISSING_USER_NAME_ATTRIBUTE_ERROR_CODE = "missing_user_name_attribute";
    private static final String INVALID_USER_INFO_RESPONSE_ERROR_CODE = "invalid_user_info_response";
    private static final ParameterizedTypeReference> PARAMETERIZED_RESPONSE_TYPE = new ParameterizedTypeReference>() {
    };
    private Converter> requestEntityConverter = new OAuth2UserRequestEntityConverter();
    private RestOperations restOperations;

    public DefaultOAuth2UserService() {
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler());
        this.restOperations = restTemplate;
    }

    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
        Assert.notNull(userRequest, "userRequest cannot be null");
        if (!StringUtils.hasText(userRequest.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUri())) {
            OAuth2Error oauth2Error = new OAuth2Error("missing_user_info_uri", "Missing required UserInfo Uri in UserInfoEndpoint for Client Registration: " + userRequest.getClientRegistration().getRegistrationId(), (String)null);
            throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString());
        } else {
            String userNameAttributeName = userRequest.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName();
            if (!StringUtils.hasText(userNameAttributeName)) {
                OAuth2Error oauth2Error = new OAuth2Error("missing_user_name_attribute", "Missing required \"user name\" attribute name in UserInfoEndpoint for Client Registration: " + userRequest.getClientRegistration().getRegistrationId(), (String)null);
                throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString());
            } else {
                RequestEntity request = (RequestEntity)this.requestEntityConverter.convert(userRequest);

                ResponseEntity response;
                OAuth2Error oauth2Error;
                try {
                    response = this.restOperations.exchange(request, PARAMETERIZED_RESPONSE_TYPE);
                } catch (OAuth2AuthorizationException var10) {
                    oauth2Error = var10.getError();
                    StringBuilder errorDetails = new StringBuilder();
                    errorDetails.append("Error details: [");
                    errorDetails.append("UserInfo Uri: ").append(userRequest.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUri());
                    errorDetails.append(", Error Code: ").append(oauth2Error.getErrorCode());
                    if (oauth2Error.getDescription() != null) {
                        errorDetails.append(", Error Description: ").append(oauth2Error.getDescription());
                    }

                    errorDetails.append("]");
                    oauth2Error = new OAuth2Error("invalid_user_info_response", "An error occurred while attempting to retrieve the UserInfo Resource: " + errorDetails.toString(), (String)null);
                    throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString(), var10);
                } catch (RestClientException var11) {
                    oauth2Error = new OAuth2Error("invalid_user_info_response", "An error occurred while attempting to retrieve the UserInfo Resource: " + var11.getMessage(), (String)null);
                    throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString(), var11);
                }

                Map userAttributes = (Map)response.getBody();
                Set authorities = new LinkedHashSet();
                authorities.add(new OAuth2UserAuthority(userAttributes));  //给用户添加默认的权限:ROLE_USER

                OAuth2AccessToken token = userRequest.getAccessToken();
                Iterator var8 = token.getScopes().iterator();

                while(var8.hasNext()) {
                    String authority = (String)var8.next();
                    authorities.add(new SimpleGrantedAuthority("SCOPE_" + authority));
                }//读取OAuth2AccessToken中的scopes,添加对应的权限,前缀为:SCOPE_

                return new DefaultOAuth2User(authorities, userAttributes, userNameAttributeName);
            }
        }
    }

    public final void setRequestEntityConverter(Converter> requestEntityConverter) {
        Assert.notNull(requestEntityConverter, "requestEntityConverter cannot be null");
        this.requestEntityConverter = requestEntityConverter;
    }

    public final void setRestOperations(RestOperations restOperations) {
        Assert.notNull(restOperations, "restOperations cannot be null");
        this.restOperations = restOperations;
    }
}

 

OAuth2UserAuthority:用户权限类

public class OAuth2UserAuthority implements GrantedAuthority {
    private static final long serialVersionUID = 520L;
    private final String authority;
    private final Map attributes;

    public OAuth2UserAuthority(Map attributes) {
        this("ROLE_USER", attributes);
    }

    public OAuth2UserAuthority(String authority, Map attributes) {
        Assert.hasText(authority, "authority cannot be empty");
        Assert.notEmpty(attributes, "attributes cannot be empty");
        this.authority = authority;
        this.attributes = Collections.unmodifiableMap(new LinkedHashMap(attributes));
    }

    public String getAuthority() {
    public Map getAttributes() {

    public boolean equals(Object obj) {
    public int hashCode() {

    public String toString() {
        return this.getAuthority();
    }
}

 

DefaultOAuth2User:默认用户类

public class DefaultOAuth2User implements OAuth2User, Serializable {
    private static final long serialVersionUID = 520L;
    private final Set authorities;
    private final Map attributes;
    private final String nameAttributeKey;

    public DefaultOAuth2User(Collection authorities, Map attributes, String nameAttributeKey) {
        Assert.notEmpty(authorities, "authorities cannot be empty");
        Assert.notEmpty(attributes, "attributes cannot be empty");
        Assert.hasText(nameAttributeKey, "nameAttributeKey cannot be empty");
        if (!attributes.containsKey(nameAttributeKey)) {
            throw new IllegalArgumentException("Missing attribute '" + nameAttributeKey + "' in attributes");
        } else {
            this.authorities = Collections.unmodifiableSet(new LinkedHashSet(this.sortAuthorities(authorities)));
            this.attributes = Collections.unmodifiableMap(new LinkedHashMap(attributes));
            this.nameAttributeKey = nameAttributeKey;
        }
    }

    public String getName() {
        return this.getAttribute(this.nameAttributeKey).toString();
    }

    public Collection getAuthorities() {
    public Map getAttributes() {
    private Set sortAuthorities(Collection authorities) {

    public boolean equals(Object obj) {
    public int hashCode() {

    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("Name: [");
        sb.append(this.getName());
        sb.append("], Granted Authorities: [");
        sb.append(this.getAuthorities());
        sb.append("], User Attributes: [");
        sb.append(this.getAttributes());
        sb.append("]");
        return sb.toString();
    }
}

 

 

**************************

相关过滤器

 

DefaultLoginPageGeneratingFilter:生成默认的登陆页面

public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
    public static final String DEFAULT_LOGIN_PAGE_URL = "/login";
    public static final String ERROR_PARAMETER_NAME = "error";
    private String loginPageUrl;
    private String logoutSuccessUrl;
    private String failureUrl;
    private boolean formLoginEnabled;
    private boolean openIdEnabled;
    private boolean oauth2LoginEnabled;
    private boolean saml2LoginEnabled;
    private String authenticationUrl;
    private String usernameParameter;
    private String passwordParameter;
    private String rememberMeParameter;
    private String openIDauthenticationUrl;
    private String openIDusernameParameter;
    private String openIDrememberMeParameter;
    private Map oauth2AuthenticationUrlToClientName;
    private Map saml2AuthenticationUrlToProviderName;
    private Function> resolveHiddenInputs = (request) -> {
        return Collections.emptyMap();
    };

    public DefaultLoginPageGeneratingFilter() {
    public DefaultLoginPageGeneratingFilter(AbstractAuthenticationProcessingFilter filter) {
    public DefaultLoginPageGeneratingFilter(UsernamePasswordAuthenticationFilter authFilter, AbstractAuthenticationProcessingFilter openIDFilter) {

    private void init(UsernamePasswordAuthenticationFilter authFilter, AbstractAuthenticationProcessingFilter openIDFilter) {
        this.loginPageUrl = "/login";
        this.logoutSuccessUrl = "/login?logout";
        this.failureUrl = "/login?error";
        if (authFilter != null) {
            this.formLoginEnabled = true;
            this.usernameParameter = authFilter.getUsernameParameter();
            this.passwordParameter = authFilter.getPasswordParameter();
            if (authFilter.getRememberMeServices() instanceof AbstractRememberMeServices) {
                this.rememberMeParameter = ((AbstractRememberMeServices)authFilter.getRememberMeServices()).getParameter();
            }
        }

        if (openIDFilter != null) {
            this.openIdEnabled = true;
            this.openIDusernameParameter = "openid_identifier";
            if (openIDFilter.getRememberMeServices() instanceof AbstractRememberMeServices) {
                this.openIDrememberMeParameter = ((AbstractRememberMeServices)openIDFilter.getRememberMeServices()).getParameter();
            }
        }

    }

 

OAuth2AuthorizationRequestRedirectFilter:授权请求跳转过滤器

public class OAuth2AuthorizationRequestRedirectFilter extends OncePerRequestFilter {
    public static final String DEFAULT_AUTHORIZATION_REQUEST_BASE_URI = "/oauth2/authorization";
    private final ThrowableAnalyzer throwableAnalyzer;
    private final RedirectStrategy authorizationRedirectStrategy;
    private OAuth2AuthorizationRequestResolver authorizationRequestResolver;
    private AuthorizationRequestRepository authorizationRequestRepository;
    private RequestCache requestCache;

    public OAuth2AuthorizationRequestRedirectFilter(ClientRegistrationRepository clientRegistrationRepository) {
        this(clientRegistrationRepository, "/oauth2/authorization");
    }

    public OAuth2AuthorizationRequestRedirectFilter(ClientRegistrationRepository clientRegistrationRepository, String authorizationRequestBaseUri) {

    public OAuth2AuthorizationRequestRedirectFilter(OAuth2AuthorizationRequestResolver authorizationRequestResolver) {

 

OAuth2LoginAuthenticationFilter:获取授权码code后的认证过滤器

public class OAuth2LoginAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
    public static final String DEFAULT_FILTER_PROCESSES_URI = "/login/oauth2/code/*";
    private static final String AUTHORIZATION_REQUEST_NOT_FOUND_ERROR_CODE = "authorization_request_not_found";
    private static final String CLIENT_REGISTRATION_NOT_FOUND_ERROR_CODE = "client_registration_not_found";
    private ClientRegistrationRepository clientRegistrationRepository;
    private OAuth2AuthorizedClientRepository authorizedClientRepository;
    private AuthorizationRequestRepository authorizationRequestRepository;

    public OAuth2LoginAuthenticationFilter(ClientRegistrationRepository clientRegistrationRepository, OAuth2AuthorizedClientService authorizedClientService) {
        this(clientRegistrationRepository, authorizedClientService, "/login/oauth2/code/*");
    }

    public OAuth2LoginAuthenticationFilter(ClientRegistrationRepository clientRegistrationRepository, OAuth2AuthorizedClientService authorizedClientService, String filterProcessesUrl) {

    public OAuth2LoginAuthenticationFilter(ClientRegistrationRepository clientRegistrationRepository, OAuth2AuthorizedClientRepository authorizedClientRepository, String filterProcessesUrl) {

 

 

你可能感兴趣的:(spring,security)