赞
踩
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) {
- ServerOAuth2AuthorizationCodeAuthenticationTokenConverter authenticationConverter = new ServerOAuth2AuthorizationCodeAuthenticationTokenConverter(clientRegistrationRepository);
- authenticationConverter.setAuthorizationRequestRepository(this.getAuthorizationRequestRepository());
- this.authenticationConverter = authenticationConverter;
- }
-
- return this.authenticationConverter;
- }
-
- public ServerHttpSecurity.OAuth2LoginSpec clientRegistrationRepository(ReactiveClientRegistrationRepository clientRegistrationRepository) {
- this.clientRegistrationRepository = clientRegistrationRepository;
- return this;
- }
-
- public ServerHttpSecurity.OAuth2LoginSpec authorizedClientService(ReactiveOAuth2AuthorizedClientService authorizedClientService) {
- this.authorizedClientRepository = new AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository(authorizedClientService);
- return this;
- }
-
- public ServerHttpSecurity.OAuth2LoginSpec authorizedClientRepository(ServerOAuth2AuthorizedClientRepository authorizedClientRepository) {
- public ServerHttpSecurity.OAuth2LoginSpec authorizationRequestRepository(ServerAuthorizationRequestRepository<OAuth2AuthorizationRequest> authorizationRequestRepository) {
- public ServerHttpSecurity.OAuth2LoginSpec authorizationRequestResolver(ServerOAuth2AuthorizationRequestResolver authorizationRequestResolver) {
- public ServerHttpSecurity.OAuth2LoginSpec authenticationMatcher(ServerWebExchangeMatcher authenticationMatcher) {
-
- private ServerWebExchangeMatcher getAuthenticationMatcher() {
- if (this.authenticationMatcher == null) {
- this.authenticationMatcher = this.createAttemptAuthenticationRequestMatcher();
- } //如果没有设置authenticationManager,则创建默认的authenticationManager
-
- return this.authenticationMatcher;
- }
-
- public ServerHttpSecurity and() {
- return ServerHttpSecurity.this;
- }
-
- protected void configure(ServerHttpSecurity http) {
- ReactiveClientRegistrationRepository clientRegistrationRepository = this.getClientRegistrationRepository(); //获取clientRegistration
- ServerOAuth2AuthorizedClientRepository authorizedClientRepository = this.getAuthorizedClientRepository(); //获取authorizedClient
-
-
- OAuth2AuthorizationRequestRedirectWebFilter oauthRedirectFilter = this.getRedirectWebFilter(); //认证请求跳转过滤器,获取授权码
- ServerAuthorizationRequestRepository<OAuth2AuthorizationRequest> authorizationRequestRepository = this.getAuthorizationRequestRepository();
- oauthRedirectFilter.setAuthorizationRequestRepository(authorizationRequestRepository);
- oauthRedirectFilter.setRequestCache(http.requestCache.requestCache);
-
-
- ReactiveAuthenticationManager manager = this.getAuthenticationManager(); //获取access_token、oauth2User
- AuthenticationWebFilter authenticationFilter = new OAuth2LoginAuthenticationWebFilter(manager, authorizedClientRepository);
- authenticationFilter.setRequiresAuthenticationMatcher(this.getAuthenticationMatcher());
- authenticationFilter.setServerAuthenticationConverter(this.getAuthenticationConverter(clientRegistrationRepository));
- authenticationFilter.setAuthenticationSuccessHandler(this.getAuthenticationSuccessHandler(http));
- authenticationFilter.setAuthenticationFailureHandler(this.getAuthenticationFailureHandler());
- authenticationFilter.setSecurityContextRepository(this.securityContextRepository);
-
-
- this.setDefaultEntryPoints(http);
- http.addFilterAt(oauthRedirectFilter, SecurityWebFiltersOrder.HTTP_BASIC);
- http.addFilterAt(authenticationFilter, SecurityWebFiltersOrder.AUTHENTICATION);
- }
-
- private void setDefaultEntryPoints(ServerHttpSecurity http) {
- String defaultLoginPage = "/login";
- Map<String, String> urlToText = http.oauth2Login.getLinks();
- String providerLoginPage = null;
- if (urlToText.size() == 1) {
- providerLoginPage = (String)urlToText.keySet().iterator().next();
- }
-
- MediaTypeServerWebExchangeMatcher htmlMatcher = new MediaTypeServerWebExchangeMatcher(new MediaType[]{MediaType.APPLICATION_XHTML_XML, new MediaType("image", "*"), MediaType.TEXT_HTML, MediaType.TEXT_PLAIN});
- htmlMatcher.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL));
- ServerWebExchangeMatcher xhrMatcher = (exchange) -> {
- return exchange.getRequest().getHeaders().getOrEmpty("X-Requested-With").contains("XMLHttpRequest") ? MatchResult.match() : MatchResult.notMatch();
- };
- ServerWebExchangeMatcher notXhrMatcher = new NegatedServerWebExchangeMatcher(xhrMatcher);
- ServerWebExchangeMatcher defaultEntryPointMatcher = new AndServerWebExchangeMatcher(new ServerWebExchangeMatcher[]{notXhrMatcher, htmlMatcher});
- if (providerLoginPage != null) {
- ServerWebExchangeMatcher loginPageMatcher = new PathPatternParserServerWebExchangeMatcher(defaultLoginPage);
- ServerWebExchangeMatcher faviconMatcher = new PathPatternParserServerWebExchangeMatcher("/favicon.ico");
- ServerWebExchangeMatcher defaultLoginPageMatcher = new AndServerWebExchangeMatcher(new ServerWebExchangeMatcher[]{new OrServerWebExchangeMatcher(new ServerWebExchangeMatcher[]{loginPageMatcher, faviconMatcher}), defaultEntryPointMatcher});
- ServerWebExchangeMatcher matcher = new AndServerWebExchangeMatcher(new ServerWebExchangeMatcher[]{notXhrMatcher, new NegatedServerWebExchangeMatcher(defaultLoginPageMatcher)});
- RedirectServerAuthenticationEntryPoint entryPoint = new RedirectServerAuthenticationEntryPoint(providerLoginPage);
- entryPoint.setRequestCache(http.requestCache.requestCache);
- http.defaultEntryPoints.add(new DelegateEntry(matcher, entryPoint));
- }
-
- RedirectServerAuthenticationEntryPoint defaultEntryPoint = new RedirectServerAuthenticationEntryPoint(defaultLoginPage);
- defaultEntryPoint.setRequestCache(http.requestCache.requestCache);
- http.defaultEntryPoints.add(new DelegateEntry(defaultEntryPointMatcher, defaultEntryPoint));
- }
-
- private ServerAuthenticationSuccessHandler getAuthenticationSuccessHandler(ServerHttpSecurity http) {
- if (this.authenticationSuccessHandler == null) {
- RedirectServerAuthenticationSuccessHandler handler = new RedirectServerAuthenticationSuccessHandler();
- handler.setRequestCache(http.requestCache.requestCache);
- this.authenticationSuccessHandler = handler;
- }
-
- return this.authenticationSuccessHandler;
- }
-
- private ServerAuthenticationFailureHandler getAuthenticationFailureHandler() {
- if (this.authenticationFailureHandler == null) {
- this.authenticationFailureHandler = new RedirectServerAuthenticationFailureHandler("/login?error");
- }
-
- return this.authenticationFailureHandler;
- }
-
- private ServerWebExchangeMatcher createAttemptAuthenticationRequestMatcher() {
- return new PathPatternParserServerWebExchangeMatcher("/login/oauth2/code/{registrationId}");
- }
-
- private ReactiveOAuth2UserService<OidcUserRequest, OidcUser> getOidcUserService() {
- ResolvableType type = ResolvableType.forClassWithGenerics(ReactiveOAuth2UserService.class, new Class[]{OidcUserRequest.class, OidcUser.class});
- ReactiveOAuth2UserService<OidcUserRequest, OidcUser> bean = (ReactiveOAuth2UserService)ServerHttpSecurity.this.getBeanOrNull(type);
- return (ReactiveOAuth2UserService)(bean == null ? new OidcReactiveOAuth2UserService() : bean);
- }
-
- private ReactiveOAuth2UserService<OAuth2UserRequest, OAuth2User> getOauth2UserService() {
- //获取认证用户操作类
- ResolvableType type = ResolvableType.forClassWithGenerics(ReactiveOAuth2UserService.class, new Class[]{OAuth2UserRequest.class, OAuth2User.class});
- ReactiveOAuth2UserService<OAuth2UserRequest, OAuth2User> bean = (ReactiveOAuth2UserService)ServerHttpSecurity.this.getBeanOrNull(type);
- return (ReactiveOAuth2UserService)(bean == null ? new DefaultReactiveOAuth2UserService() : bean);
- }
-
- private Map<String, String> getLinks() {
- Iterable<ClientRegistration> registrations = (Iterable)ServerHttpSecurity.this.getBeanOrNull(ResolvableType.forClassWithGenerics(Iterable.class, new Class[]{ClientRegistration.class}));
- if (registrations == null) {
- return Collections.emptyMap();
- } else {
- Map<String, String> result = new HashMap();
- registrations.iterator().forEachRemaining((r) -> {
- String var10000 = (String)result.put("/oauth2/authorization/" + r.getRegistrationId(), r.getClientName());
- });
- return result;
- }
- }
-
- private ReactiveOAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> getAccessTokenResponseClient() {
- ResolvableType type = ResolvableType.forClassWithGenerics(ReactiveOAuth2AccessTokenResponseClient.class, new Class[]{OAuth2AuthorizationCodeGrantRequest.class});
- ReactiveOAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> bean = (ReactiveOAuth2AccessTokenResponseClient)ServerHttpSecurity.this.getBeanOrNull(type);
- return (ReactiveOAuth2AccessTokenResponseClient)(bean == null ? new WebClientReactiveAuthorizationCodeTokenResponseClient() : bean);
- }
-
- private ReactiveClientRegistrationRepository getClientRegistrationRepository() {
- if (this.clientRegistrationRepository == null) {
- this.clientRegistrationRepository = (ReactiveClientRegistrationRepository)ServerHttpSecurity.this.getBeanOrNull(ReactiveClientRegistrationRepository.class);
- }
-
- return this.clientRegistrationRepository;
- }
-
- private OAuth2AuthorizationRequestRedirectWebFilter getRedirectWebFilter() {
- OAuth2AuthorizationRequestRedirectWebFilter oauthRedirectFilter;
- if (this.authorizationRequestResolver == null) {
- oauthRedirectFilter = new OAuth2AuthorizationRequestRedirectWebFilter(this.getClientRegistrationRepository());
- } else {
- oauthRedirectFilter = new OAuth2AuthorizationRequestRedirectWebFilter(this.authorizationRequestResolver);
- }
-
- return oauthRedirectFilter;
- }
-
- private ServerOAuth2AuthorizedClientRepository getAuthorizedClientRepository() {
- ServerOAuth2AuthorizedClientRepository result = this.authorizedClientRepository;
- if (result == null) {
- result = (ServerOAuth2AuthorizedClientRepository)ServerHttpSecurity.this.getBeanOrNull(ServerOAuth2AuthorizedClientRepository.class);
- }
-
- if (result == null) {
- ReactiveOAuth2AuthorizedClientService authorizedClientService = this.getAuthorizedClientService();
- if (authorizedClientService != null) {
- result = new AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository(authorizedClientService);
- }
- }
-
- return (ServerOAuth2AuthorizedClientRepository)result;
- }
-
- private ServerAuthorizationRequestRepository<OAuth2AuthorizationRequest> getAuthorizationRequestRepository() {
- if (this.authorizationRequestRepository == null) {
- this.authorizationRequestRepository = new WebSessionOAuth2ServerAuthorizationRequestRepository();
- }
-
- return this.authorizationRequestRepository;
- }
-
- private ReactiveOAuth2AuthorizedClientService getAuthorizedClientService() {
- ReactiveOAuth2AuthorizedClientService service = (ReactiveOAuth2AuthorizedClientService)ServerHttpSecurity.this.getBeanOrNull(ReactiveOAuth2AuthorizedClientService.class);
- if (service == null) {
- service = new InMemoryReactiveOAuth2AuthorizedClientService(this.getClientRegistrationRepository());
- }
-
- return (ReactiveOAuth2AuthorizedClientService)service;
- }
-
- private OAuth2LoginSpec() {
- }
- }
*****************
ReactiveClientRegistrationRepository
ReactiveClientRegistrationRepository:存储授权提供方
- public interface ReactiveClientRegistrationRepository {
- Mono<ClientRegistration> findByRegistrationId(String var1);
- }
InMemoryReactiveClientRegistrationRepository:内存中存储clientRegistration
- public final class InMemoryReactiveClientRegistrationRepository implements ReactiveClientRegistrationRepository, Iterable<ClientRegistration> {
- private final Map<String, ClientRegistration> clientIdToClientRegistration;
-
- public InMemoryReactiveClientRegistrationRepository(ClientRegistration... registrations) {
- this(toList(registrations));
- }
-
- private static List<ClientRegistration> toList(ClientRegistration... registrations) {
- Assert.notEmpty(registrations, "registrations cannot be null or empty");
- return Arrays.asList(registrations);
- }
-
- public InMemoryReactiveClientRegistrationRepository(List<ClientRegistration> registrations) {
- this.clientIdToClientRegistration = toUnmodifiableConcurrentMap(registrations);
- }
-
- public Mono<ClientRegistration> findByRegistrationId(String registrationId) {
- return Mono.justOrEmpty(this.clientIdToClientRegistration.get(registrationId));
- }
-
- public Iterator<ClientRegistration> iterator() {
- return this.clientIdToClientRegistration.values().iterator();
- }
-
- private static Map<String, ClientRegistration> toUnmodifiableConcurrentMap(List<ClientRegistration> registrations) {
- Assert.notEmpty(registrations, "registrations cannot be null or empty");
- ConcurrentHashMap<String, ClientRegistration> result = new ConcurrentHashMap();
- Iterator var2 = registrations.iterator();
-
- while(var2.hasNext()) {
- ClientRegistration registration = (ClientRegistration)var2.next();
- Assert.notNull(registration, "no registration can be null");
- if (result.containsKey(registration.getRegistrationId())) {
- throw new IllegalStateException(String.format("Duplicate key %s", registration.getRegistrationId()));
- }
-
- result.put(registration.getRegistrationId(), registration);
- }
-
- return Collections.unmodifiableMap(result);
- }
- }
clientRegistration: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<String> scopes;
- private ClientRegistration.ProviderDetails providerDetails;
- private String clientName;
-
-
- ***********
- 内部类: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<String, Object> configurationMetadata;
*****************
authenticationManager
ReactiveAuthenticationManager:认证authentication接口
- @FunctionalInterface
- public interface ReactiveAuthenticationManager {
- Mono<Authentication> authenticate(Authentication var1);
- }
OAuth2LoginReactiveAuthenticationManager:认证autentication,认证成功后加载认证用户
- public class OAuth2LoginReactiveAuthenticationManager implements ReactiveAuthenticationManager {
- private final ReactiveAuthenticationManager authorizationCodeManager;
- private final ReactiveOAuth2UserService<OAuth2UserRequest, OAuth2User> userService;
- private GrantedAuthoritiesMapper authoritiesMapper = (authorities) -> {
- return authorities;
- };
-
- public OAuth2LoginReactiveAuthenticationManager(ReactiveOAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> accessTokenResponseClient, ReactiveOAuth2UserService<OAuth2UserRequest, OAuth2User> userService) {
- Assert.notNull(accessTokenResponseClient, "accessTokenResponseClient cannot be null");
- Assert.notNull(userService, "userService cannot be null");
- this.authorizationCodeManager = new OAuth2AuthorizationCodeReactiveAuthenticationManager(accessTokenResponseClient);
- this.userService = userService;
- }
-
- public Mono<Authentication> authenticate(Authentication authentication) {
- //认证authentication
-
- return Mono.defer(() -> {
- OAuth2AuthorizationCodeAuthenticationToken token = (OAuth2AuthorizationCodeAuthenticationToken)authentication;
- return token.getAuthorizationExchange().getAuthorizationRequest().getScopes().contains("openid") ? Mono.empty() : this.authorizationCodeManager.authenticate(token).onErrorMap(OAuth2AuthorizationException.class, (e) -> {
- return new OAuth2AuthenticationException(e.getError(), e.getError().toString());
- }).cast(OAuth2AuthorizationCodeAuthenticationToken.class).flatMap(this::onSuccess);
- });
- }
-
- private Mono<OAuth2LoginAuthenticationToken> onSuccess(OAuth2AuthorizationCodeAuthenticationToken authentication) {
- //认证成功后,加载认证用户
- OAuth2AccessToken accessToken = authentication.getAccessToken();
- Map<String, Object> additionalParameters = authentication.getAdditionalParameters();
- OAuth2UserRequest userRequest = new OAuth2UserRequest(authentication.getClientRegistration(), accessToken, additionalParameters);
- return this.userService.loadUser(userRequest).map((oauth2User) -> {
- Collection<? extends GrantedAuthority> mappedAuthorities = this.authoritiesMapper.mapAuthorities(oauth2User.getAuthorities());
- OAuth2LoginAuthenticationToken authenticationResult = new OAuth2LoginAuthenticationToken(authentication.getClientRegistration(), authentication.getAuthorizationExchange(), oauth2User, mappedAuthorities, accessToken, authentication.getRefreshToken());
- return authenticationResult;
- });
- }
- }
ReactiveOAuth2UserService:加载认证用户接口
- @FunctionalInterface
- public interface ReactiveOAuth2UserService<R extends OAuth2UserRequest, U extends OAuth2User> {
- Mono<U> loadUser(R var1) throws OAuth2AuthenticationException;
- }
DefaultReactiveOAuth2UserService:默认加载认证用户实现类
- public class DefaultReactiveOAuth2UserService implements ReactiveOAuth2UserService<OAuth2UserRequest, OAuth2User> {
- private static final String INVALID_USER_INFO_RESPONSE_ERROR_CODE = "invalid_user_info_response";
- 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 WebClient webClient = WebClient.create();
-
- public DefaultReactiveOAuth2UserService() {
- }
-
- public Mono<OAuth2User> loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
- //加载认证用户
- return Mono.defer(() -> {
- Assert.notNull(userRequest, "userRequest cannot be null");
- String userInfoUri = userRequest.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUri();
- if (!StringUtils.hasText(userInfoUri)) {
- 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 oauth2Errorx = 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(oauth2Errorx, oauth2Errorx.toString());
- } else {
- ParameterizedTypeReference<Map<String, Object>> typeReference = new ParameterizedTypeReference<Map<String, Object>>() {
- };
- AuthenticationMethod authenticationMethod = userRequest.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getAuthenticationMethod();
- RequestHeadersSpec requestHeadersSpec;
- if (AuthenticationMethod.FORM.equals(authenticationMethod)) {
- requestHeadersSpec = ((RequestBodySpec)((RequestBodySpec)((RequestBodySpec)this.webClient.post().uri(userInfoUri, new Object[0])).header("Accept", new String[]{"application/json"})).header("Content-Type", new String[]{"application/x-www-form-urlencoded"})).syncBody("access_token=" + userRequest.getAccessToken().getTokenValue());
- } else {
- requestHeadersSpec = this.webClient.get().uri(userInfoUri, new Object[0]).header("Accept", new String[]{"application/json"}).headers((headers) -> {
- headers.setBearerAuth(userRequest.getAccessToken().getTokenValue());
- });
- }
-
- Mono<Map<String, Object>> userAttributes = requestHeadersSpec.retrieve().onStatus((s) -> {
- return s != HttpStatus.OK;
- }, (response) -> {
- return parse(response).map((userInfoErrorResponse) -> {
- String description = userInfoErrorResponse.getErrorObject().getDescription();
- OAuth2Error oauth2Error = new OAuth2Error("invalid_user_info_response", description, (String)null);
- throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString());
- });
- }).bodyToMono(typeReference);
- return userAttributes.map((attrs) -> {
- GrantedAuthority authority = new OAuth2UserAuthority(attrs);
- Set<GrantedAuthority> authorities = new HashSet();
- authorities.add(authority);
- OAuth2AccessToken token = userRequest.getAccessToken();
- Iterator var6 = token.getScopes().iterator();
-
- while(var6.hasNext()) {
- String scope = (String)var6.next();
- authorities.add(new SimpleGrantedAuthority("SCOPE_" + scope));
- }
-
- return new DefaultOAuth2User(authorities, attrs, userNameAttributeName);
- }).onErrorMap((e) -> {
- return e instanceof IOException;
- }, (t) -> {
- return new AuthenticationServiceException("Unable to access the userInfoEndpoint " + userInfoUri, t);
- }).onErrorMap((t) -> {
- return !(t instanceof AuthenticationServiceException);
- }, (t) -> {
- OAuth2Error oauth2Error = new OAuth2Error("invalid_user_info_response", "An error occurred reading the UserInfo Success response: " + t.getMessage(), (String)null);
- return new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString(), t);
- });
- }
- }
- });
- }
-
- public void setWebClient(WebClient webClient) {
- Assert.notNull(webClient, "webClient cannot be null");
- this.webClient = webClient;
- }
-
- private static Mono<UserInfoErrorResponse> parse(ClientResponse httpResponse) {
- String wwwAuth = httpResponse.headers().asHttpHeaders().getFirst("WWW-Authenticate");
- if (!StringUtils.isEmpty(wwwAuth)) {
- return Mono.fromCallable(() -> {
- return UserInfoErrorResponse.parse(wwwAuth);
- });
- } else {
- ParameterizedTypeReference<Map<String, String>> typeReference = new ParameterizedTypeReference<Map<String, String>>() {
- };
- return httpResponse.bodyToMono(typeReference).map((body) -> {
- return new UserInfoErrorResponse(ErrorObject.parse(new JSONObject(body)));
- });
- }
- }
- }
*****************
获取 access_token
WebClientReactiveAuthorizationCodeTokenResponseClient:获取access_token的客户端
- public class WebClientReactiveAuthorizationCodeTokenResponseClient extends AbstractWebClientReactiveOAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> {
- public WebClientReactiveAuthorizationCodeTokenResponseClient() {
- }
-
- ClientRegistration clientRegistration(OAuth2AuthorizationCodeGrantRequest grantRequest) {
- return grantRequest.getClientRegistration();
- }
-
- Set<String> scopes(OAuth2AuthorizationCodeGrantRequest grantRequest) {
- return Collections.emptySet();
- }
-
- Set<String> defaultScopes(OAuth2AuthorizationCodeGrantRequest grantRequest) {
- return grantRequest.getAuthorizationExchange().getAuthorizationRequest().getScopes();
- }
-
- FormInserter<String> populateTokenRequestBody(OAuth2AuthorizationCodeGrantRequest grantRequest, FormInserter<String> body) {
- super.populateTokenRequestBody(grantRequest, body);
- OAuth2AuthorizationExchange authorizationExchange = grantRequest.getAuthorizationExchange();
- OAuth2AuthorizationResponse authorizationResponse = authorizationExchange.getAuthorizationResponse();
- body.with("code", authorizationResponse.getCode());
- String redirectUri = authorizationExchange.getAuthorizationRequest().getRedirectUri();
- if (redirectUri != null) {
- body.with("redirect_uri", redirectUri);
- }
-
- String codeVerifier = (String)authorizationExchange.getAuthorizationRequest().getAttribute("code_verifier");
- if (codeVerifier != null) {
- body.with("code_verifier", codeVerifier);
- }
-
- return body;
- }
- }
AbstractWebClientOAuth2ReactiveAccessTokenResponseClient:使用webClient获取acccess_token
- abstract class AbstractWebClientReactiveOAuth2AccessTokenResponseClient<T extends AbstractOAuth2AuthorizationGrantRequest> implements ReactiveOAuth2AccessTokenResponseClient<T> {
- private WebClient webClient = WebClient.builder().build();
-
- AbstractWebClientReactiveOAuth2AccessTokenResponseClient() {
- }
-
- public Mono<OAuth2AccessTokenResponse> getTokenResponse(T grantRequest) {
- Assert.notNull(grantRequest, "grantRequest cannot be null");
- return Mono.defer(() -> {
- return ((RequestBodySpec)((RequestBodySpec)this.webClient.post().uri(this.clientRegistration(grantRequest).getProviderDetails().getTokenUri(), new Object[0])).headers((headers) -> {
- this.populateTokenRequestHeaders(grantRequest, headers);
- })).body(this.createTokenRequestBody(grantRequest)).exchange().flatMap((response) -> {
- return this.readTokenResponse(grantRequest, response);
- });
- });
- }
-
- abstract ClientRegistration clientRegistration(T var1);
-
- private void populateTokenRequestHeaders(T grantRequest, HttpHeaders headers) {
- ClientRegistration clientRegistration = this.clientRegistration(grantRequest);
- headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
- headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
- if (ClientAuthenticationMethod.BASIC.equals(clientRegistration.getClientAuthenticationMethod())) {
- headers.setBasicAuth(clientRegistration.getClientId(), clientRegistration.getClientSecret());
- }
-
- }
-
- private FormInserter<String> createTokenRequestBody(T grantRequest) {
- FormInserter<String> body = BodyInserters.fromFormData("grant_type", grantRequest.getGrantType().getValue());
- return this.populateTokenRequestBody(grantRequest, body);
- }
-
- FormInserter<String> populateTokenRequestBody(T grantRequest, FormInserter<String> body) {
- ClientRegistration clientRegistration = this.clientRegistration(grantRequest);
- if (!ClientAuthenticationMethod.BASIC.equals(clientRegistration.getClientAuthenticationMethod())) {
- body.with("client_id", clientRegistration.getClientId());
- }
-
- if (ClientAuthenticationMethod.POST.equals(clientRegistration.getClientAuthenticationMethod())) {
- body.with("client_secret", clientRegistration.getClientSecret());
- }
-
- Set<String> scopes = this.scopes(grantRequest);
- if (!CollectionUtils.isEmpty(scopes)) {
- body.with("scope", StringUtils.collectionToDelimitedString(scopes, " "));
- }
-
- return body;
- }
-
- abstract Set<String> scopes(T var1);
-
- Set<String> defaultScopes(T grantRequest) {
- return this.scopes(grantRequest);
- }
-
- private Mono<OAuth2AccessTokenResponse> readTokenResponse(T grantRequest, ClientResponse response) {
- return ((Mono)response.body(OAuth2BodyExtractors.oauth2AccessTokenResponse())).map((tokenResponse) -> {
- return this.populateTokenResponse(grantRequest, tokenResponse);
- });
- }
-
- OAuth2AccessTokenResponse populateTokenResponse(T grantRequest, OAuth2AccessTokenResponse tokenResponse) {
- if (CollectionUtils.isEmpty(tokenResponse.getAccessToken().getScopes())) {
- Set<String> defaultScopes = this.defaultScopes(grantRequest);
- tokenResponse = OAuth2AccessTokenResponse.withResponse(tokenResponse).scopes(defaultScopes).build();
- }
-
- return tokenResponse;
- }
-
- public void setWebClient(WebClient webClient) {
- Assert.notNull(webClient, "webClient cannot be null");
- this.webClient = webClient;
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。