我有一個(gè)Spring啟動(dòng)應(yīng)用程序版本2.7.10
,我希望能夠通過OAuth2
向兩個(gè)身份提供程序(github
和google
)進(jìn)行身份驗(yàn)證。
基本上,我的web應(yīng)用程序應(yīng)該允許用戶選擇github
或google
進(jìn)行身份驗(yàn)證,但我無法使它同時(shí)適用于兩個(gè)身份驗(yàn)證提供程序,只有在OAuth2ClientServiceConfig.java
中有bean注釋的@Primary
。
有了這一點(diǎn),我需要兩個(gè)提供程序的配置,如下所示:
Oauth2ClientConfiguration.java
@Configuration
public class Oauth2ClientConfiguration {
@Bean(name = "github")
public ClientRegistrationRepository githubClientRegistrationRepository() {
ClientRegistration clientRegistration = ClientRegistration.withRegistrationId("github")
.clientId("GITHUB_CLIENT_ID")
.clientSecret("GITHUB_CLIENT_SECRET")
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.redirectUriTemplate("{baseUrl}/login/oauth2/code/{registrationId}")
.scope("user")
.authorizationUri("https://github.com/login/oauth/authorize")
.tokenUri("https://github.com/login/oauth/access_token")
.userInfoUri("https://api.github.com/user")
.userNameAttributeName("id")
.clientName("gitHub")
.build();
return new InMemoryClientRegistrationRepository(clientRegistration);
}
@Bean(name = "google")
public ClientRegistration clientRegistration = ClientRegistration.withRegistrationId("google")
.clientId("GOOGLE_CLIENT_ID")
.clientSecret("GOOGLE_CLIENT_SECRET")
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.redirectUri("{baseUrl}/login/oauth2/code/{registrationId}")
.scope("openid", "profile", "email", "address", "phone")
.authorizationUri("https://accounts.google.com/o/oauth2/v2/auth")
.tokenUri("https://www.googleapis.com/oauth2/v4/token")
.userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo")
.userNameAttributeName(IdTokenClaimNames.SUB)
.jwkSetUri("https://www.googleapis.com/oauth2/v3/certs")
.clientName("Google")
.build();
return new InMemoryClientRegistrationRepository(clientRegistration);
}
}
OAuth2ClientServiceConfig.java
@Configuration
public class OAuth2ClientServiceConfig {
@Bean(name = "githubClientService")
public OAuth2AuthorizedClientService githubAuthorizedClientService(
@Qualifier("github") ClientRegistrationRepository githubClientRegistrationRepository) {
return new InMemoryOAuth2AuthorizedClientService(githubClientRegistrationRepository);
}
@Bean(name = "googleClientService")
@Primary
public OAuth2AuthorizedClientService googleAuthorizedClientService(
@Qualifier("google") ClientRegistrationRepository googleClientRegistrationRepository) {
return new InMemoryOAuth2AuthorizedClientService(googleClientRegistrationRepository);
}
}
WebSecurityConfig.java
(注意類底部的note注釋)
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier("githubClientService")
private OAuth2AuthorizedClientService githubOAuth2AuthorizedClientService;
@Autowired
@Qualifier("googleClientService")
private OAuth2AuthorizedClientService googleOAuth2AuthorizedClientService;
@Autowired
@Qualifier("github")
private ClientRegistrationRepository githubClientRegistrationRepository;
@Autowired
@Qualifier("google")
private ClientRegistrationRepository googleClientRegistrationRepository;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(new CustomSecurityExceptionHandlingFilter(), UsernamePasswordAuthenticationFilter.class)
.oauth2Login()
.authorizationEndpoint()
.authorizationRequestResolver(
new CustomAuthorizationRequestResolver(
googleClientRegistrationRepository)
)
.and()
.loginPage("/login") // this one is important to not use Spring security formlogin
.clientRegistrationRepository(googleClientRegistrationRepository)
.successHandler(this::handleOAuth2Login)
}
private void handleOAuth2Login(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException {
String clientRegistrationId = "google";
OAuth2User oauth2User = (OAuth2User) authentication.getPrincipal();
// NOTE:
// - authorizedClient here is NOT null if @Primary is SET to @Bean(name = "googleClientService") in OAuth2ClientServiceConfig.java
// - authorizedClient here is null if @Primary is SET to @Bean(name = "githubClientService") in OAuth2ClientServiceConfig.java
OAuth2AuthorizedClient authorizedClient = googleOAuth2AuthorizedClientService.loadAuthorizedClient(
clientRegistrationId, oauth2User.getName())
String accessToken = authorizedClient.getAccessToken().getTokenValue();
}
}
我不確定我遺漏了什么,或者Spring安全性有一些限制,無法通過OAuth2支持通過多個(gè)身份提供程序進(jìn)行身份驗(yàn)證。
ClientRegistrationRepository
與任何存儲庫一樣,旨在管理多個(gè)注冊。