spring security webflux 三方用户授权说明
spring security 默认整合了github、google、facebook、okta三方登录功能,直接配置client-id、client-secret等参数就可自动登录;
其他三方授权方(如gitee、微博等)需要实现相关的接口
*************************
相关类及接口
CommonOAuth2Provider:默认集成的三方授权提供方
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);
}
ServerHttpSecurity:oauth2配置入口类
public class ServerHttpSecurity {
******************
内部类:ServerHttpSecurity.OAuth2LoginSpec
public class OAuth2LoginSpec {
private ReactiveClientRegistrationRepository clientRegistrationRepository; //存储授权提供方
private ServerOAuth2AuthorizedClientRepository authorizedClientRepository; //存储授权客户端
private ServerAuthorizationRequestRepository<OAuth2AuthorizationRequest> authorizationRequestRepository; //授权请求操作
private ReactiveAuthenticationManager authenticationManager; //获取access_token,成功后加载OAuth2User
private ServerSecurityContextRepository securityContextRepository;
private ServerAuthenticationConverter authenticationConverter;
private ServerOAuth2AuthorizationRequestResolver authorizationRequestResolver;
private ServerWebExchangeMatcher authenticationMatcher;
private ServerAuthenticationSuccessHandler authenticationSuccessHandler;
private ServerAuthenticationFailureHandler authenticationFailureHandler;
public ServerHttpSecurity.OAuth2LoginSpec authenticationManager(ReactiveAuthenticationManager authenticationManager) {
public ServerHttpSecurity.OAuth2LoginSpec securityContextRepository(ServerSecurityContextRepository securityContextRepository) {
public ServerHttpSecurity.OAuth2LoginSpec authenticationSuccessHandler(ServerAuthenticationSuccessHandler authenticationSuccessHandler) {
public ServerHttpSecurity.OAuth2LoginSpec authenticationFailureHandler(ServerAuthenticationFailureHandler authenticationFailureHandler) {
private ReactiveAuthenticationManager getAuthenticationManager() {
if (this.authenticationManager == null) {
this.authenticationManager = this.createDefault();
}//如果没有设置authenticationManager,则创建默认的authenticationManager
return this.authenticationManager;
}
private ReactiveAuthenticationManager createDefault() {
ReactiveOAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> client = this.getAccessTokenResponseClient();
//获取access_token客户端,如果不存在则创建WebClientReactiveAuthorizationCodeTokenResponseClient
ReactiveAuthenticationManager result = new OAuth2LoginReactiveAuthenticationManager(client, this.getOauth2UserService());
//创建OAuth2LoginReactiveAuthenticationManager,该对象可同时获取access_token、oauth2User(如果不存在,默认为DefaultReactiveOAuth2UserService对象)
boolean oidcAuthenticationProviderEnabled = ClassUtils.isPresent("org.springframework.security.oauth2.jwt.JwtDecoder", this.getClass().getClassLoader());
if (oidcAuthenticationProviderEnabled) {
OidcAuthorizationCodeReactiveAuthenticationManager oidc = new OidcAuthorizationCodeReactiveAuthenticationManager(client, this.getOidcUserService());
ResolvableType type = ResolvableType.forClassWithGenerics(ReactiveJwtDecoderFactory.class, new Class[]{ClientRegistration.class});
ReactiveJwtDecoderFactory<ClientRegistration> jwtDecoderFactory = (ReactiveJwtDecoderFactory)ServerHttpSecurity.this.getBeanOrNull(type);
if (jwtDecoderFactory != null) {
oidc.setJwtDecoderFactory(jwtDecoderFactory);
}
result = new DelegatingReactiveAuthenticationManager(new ReactiveAuthenticationManager[]{oidc, (ReactiveAuthenticationManager)result});
}
return (ReactiveAuthenticationManager)result;
}
public ServerHttpSecurity.OAuth2LoginSpec authenticationConverter(ServerAuthenticationConverter authenticationConverter) {
this.authenticationConverter = authenticationConverter;
return this;
}
private ServerAuthenticationConverter getAuthenticationConverter(ReactiveClientRegistrationRepository clientRegistrationRepository) {
if (this.authenticationConverter == null) {
ServerOAu