From 84aa6da7756ea8dbee2f1288113ed0d1c3a7a411 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=83=9D=E5=85=88=E7=91=9E?= <1490493387@qq.com> Date: Tue, 6 Jun 2023 23:00:37 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E8=AE=A4=E8=AF=81=E4=B8=AD?= =?UTF-8?q?=E5=BF=83=E5=8D=87=E7=BA=A7(=E4=B8=B4=E6=97=B6=E6=8F=90?= =?UTF-8?q?=E4=BA=A4=E5=8B=BFclone)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ceOwnerPasswordAuthenticationProvider.java | 2 +- ...ourceOwnerPasswordAuthenticationToken.java | 2 +- .../wechat/WechatAuthenticationConverter.java | 129 +++++++++++ .../wechat/WechatAuthenticationProvider.java | 206 +++++++++++++----- .../wechat/WechatAuthenticationToken.java | 73 +++---- .../wechat/WechatTokenGranter.java | 66 ------ 6 files changed, 309 insertions(+), 169 deletions(-) create mode 100644 youlai-auth/src/main/java/com/youlai/auth/authentication/wechat/WechatAuthenticationConverter.java delete mode 100644 youlai-auth/src/main/java/com/youlai/auth/authentication/wechat/WechatTokenGranter.java diff --git a/youlai-auth/src/main/java/com/youlai/auth/authentication/password/ResourceOwnerPasswordAuthenticationProvider.java b/youlai-auth/src/main/java/com/youlai/auth/authentication/password/ResourceOwnerPasswordAuthenticationProvider.java index 9226910ff..5e2a217ee 100644 --- a/youlai-auth/src/main/java/com/youlai/auth/authentication/password/ResourceOwnerPasswordAuthenticationProvider.java +++ b/youlai-auth/src/main/java/com/youlai/auth/authentication/password/ResourceOwnerPasswordAuthenticationProvider.java @@ -98,7 +98,7 @@ public class ResourceOwnerPasswordAuthenticationProvider implements Authenticati } // 生成 access_token -// @formatter:off + // @formatter:off DefaultOAuth2TokenContext.Builder tokenContextBuilder = DefaultOAuth2TokenContext.builder() .registeredClient(registeredClient) .principal(usernamePasswordAuthentication) diff --git a/youlai-auth/src/main/java/com/youlai/auth/authentication/password/ResourceOwnerPasswordAuthenticationToken.java b/youlai-auth/src/main/java/com/youlai/auth/authentication/password/ResourceOwnerPasswordAuthenticationToken.java index 2e30e9b77..4b75886f1 100644 --- a/youlai-auth/src/main/java/com/youlai/auth/authentication/password/ResourceOwnerPasswordAuthenticationToken.java +++ b/youlai-auth/src/main/java/com/youlai/auth/authentication/password/ResourceOwnerPasswordAuthenticationToken.java @@ -18,7 +18,7 @@ public class ResourceOwnerPasswordAuthenticationToken extends OAuth2Authorizatio * @param clientPrincipal * @param additionalParameters */ - protected ResourceOwnerPasswordAuthenticationToken( + public ResourceOwnerPasswordAuthenticationToken( Authentication clientPrincipal, @Nullable Set scopes, Map additionalParameters diff --git a/youlai-auth/src/main/java/com/youlai/auth/authentication/wechat/WechatAuthenticationConverter.java b/youlai-auth/src/main/java/com/youlai/auth/authentication/wechat/WechatAuthenticationConverter.java new file mode 100644 index 000000000..5cfc42a47 --- /dev/null +++ b/youlai-auth/src/main/java/com/youlai/auth/authentication/wechat/WechatAuthenticationConverter.java @@ -0,0 +1,129 @@ +package com.youlai.auth.authentication.wechat; + +import cn.hutool.core.util.StrUtil; +import com.youlai.auth.authentication.password.ResourceOwnerPasswordAuthenticationToken; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.oauth2.core.AuthorizationGrantType; +import org.springframework.security.oauth2.core.OAuth2AuthenticationException; +import org.springframework.security.oauth2.core.OAuth2Error; +import org.springframework.security.oauth2.core.OAuth2ErrorCodes; +import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; +import org.springframework.security.web.authentication.AuthenticationConverter; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.util.StringUtils; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * 参数解析 + * + * @see org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2AuthorizationCodeAuthenticationConverter + */ +public class WechatAuthenticationConverter implements AuthenticationConverter { + + public static final String ACCESS_TOKEN_REQUEST_ERROR_URI = "https://datatracker.ietf.org/doc/html/rfc6749#section-5.2"; + + + @Override + public Authentication convert(HttpServletRequest request) { + // grant_type (REQUIRED) + String grantType = request.getParameter(OAuth2ParameterNames.GRANT_TYPE); + if (!"wechat".equals(grantType)) { + return null; + } + + MultiValueMap parameters = getParameters(request); + + // scope (OPTIONAL) + String scope = parameters.getFirst(OAuth2ParameterNames.SCOPE); + if (StringUtils.hasText(scope) && + parameters.get(OAuth2ParameterNames.SCOPE).size() != 1) { + throwError( + OAuth2ErrorCodes.INVALID_REQUEST, + OAuth2ParameterNames.SCOPE, + ACCESS_TOKEN_REQUEST_ERROR_URI); + } + + Set requestedScopes = null; + if (StringUtils.hasText(scope)) { + requestedScopes = new HashSet<>( + Arrays.asList(StringUtils.delimitedListToStringArray(scope, " "))); + } + + // code (REQUIRED) + String code = parameters.getFirst("code"); + if (StrUtil.isBlank(code)) { + throwError( + OAuth2ErrorCodes.INVALID_REQUEST, + "code", + ACCESS_TOKEN_REQUEST_ERROR_URI); + } + + // encryptedData (REQUIRED) + String encryptedData = parameters.getFirst("encryptedData"); + if (StrUtil.isBlank(encryptedData)) { + throwError( + OAuth2ErrorCodes.INVALID_REQUEST, + "encryptedData", + ACCESS_TOKEN_REQUEST_ERROR_URI); + } + + // iv (REQUIRED) + String iv = parameters.getFirst("iv"); + if (StrUtil.isBlank(iv)) { + throwError( + OAuth2ErrorCodes.INVALID_REQUEST, + "iv", + ACCESS_TOKEN_REQUEST_ERROR_URI); + } + + Authentication clientPrincipal = SecurityContextHolder.getContext().getAuthentication(); + if (clientPrincipal == null) { + throwError( + OAuth2ErrorCodes.INVALID_REQUEST, + OAuth2ErrorCodes.INVALID_CLIENT, + ACCESS_TOKEN_REQUEST_ERROR_URI); + } + + Map additionalParameters = parameters + .entrySet() + .stream() + .filter(e -> !e.getKey().equals(OAuth2ParameterNames.GRANT_TYPE) && + !e.getKey().equals(OAuth2ParameterNames.SCOPE)) + .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().get(0))); + + ResourceOwnerPasswordAuthenticationToken resourceOwnerPasswordAuthenticationToken = + new ResourceOwnerPasswordAuthenticationToken( + clientPrincipal, + requestedScopes, + additionalParameters + ); + return resourceOwnerPasswordAuthenticationToken; + } + + + public static MultiValueMap getParameters(HttpServletRequest request) { + Map parameterMap = request.getParameterMap(); + MultiValueMap parameters = new LinkedMultiValueMap(parameterMap.size()); + parameterMap.forEach((key, values) -> { + for (String value : values) { + parameters.add(key, value); + } + + }); + return parameters; + } + + public static void throwError(String errorCode, String parameterName, String errorUri) { + OAuth2Error error = new OAuth2Error(errorCode, "OAuth 2.0 Parameter: " + parameterName, errorUri); + throw new OAuth2AuthenticationException(error); + } + + } diff --git a/youlai-auth/src/main/java/com/youlai/auth/authentication/wechat/WechatAuthenticationProvider.java b/youlai-auth/src/main/java/com/youlai/auth/authentication/wechat/WechatAuthenticationProvider.java index a1e778b0b..88c11e46f 100644 --- a/youlai-auth/src/main/java/com/youlai/auth/authentication/wechat/WechatAuthenticationProvider.java +++ b/youlai-auth/src/main/java/com/youlai/auth/authentication/wechat/WechatAuthenticationProvider.java @@ -1,77 +1,167 @@ package com.youlai.auth.authentication.wechat; -import cn.binarywang.wx.miniapp.api.WxMaService; -import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; -import cn.binarywang.wx.miniapp.bean.WxMaUserInfo; -import cn.hutool.core.bean.BeanUtil; -import com.youlai.auth.userdetails.member.MemberUserDetailsServiceImpl; -import com.youlai.common.result.Result; -import com.youlai.common.result.ResultCode; -import com.youlai.mall.ums.api.MemberFeignClient; -import com.youlai.mall.ums.dto.MemberAuthDTO; -import com.youlai.mall.ums.dto.MemberDTO; -import lombok.Data; -import lombok.SneakyThrows; +import cn.hutool.core.lang.Assert; +import com.youlai.auth.authentication.password.ResourceOwnerPasswordAuthenticationToken; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.oauth2.core.*; +import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; +import org.springframework.security.oauth2.core.oidc.endpoint.OidcParameterNames; +import org.springframework.security.oauth2.server.authorization.OAuth2Authorization; +import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService; +import org.springframework.security.oauth2.server.authorization.OAuth2TokenType; +import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AccessTokenAuthenticationToken; +import org.springframework.security.oauth2.server.authorization.authentication.OAuth2ClientAuthenticationToken; +import org.springframework.security.oauth2.server.authorization.client.RegisteredClient; +import org.springframework.security.oauth2.server.authorization.context.AuthorizationServerContextHolder; +import org.springframework.security.oauth2.server.authorization.token.DefaultOAuth2TokenContext; +import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenContext; +import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenGenerator; +import org.springframework.util.CollectionUtils; -import java.util.HashSet; +import java.security.Principal; +import java.util.*; +import java.util.stream.Collectors; /** * 微信认证提供者 * - * @author haoxr - * @since 2021/9/25 + * @author haoxr + * @since 3.0.0 */ -@Data +@Slf4j public class WechatAuthenticationProvider implements AuthenticationProvider { - private UserDetailsService userDetailsService; - private WxMaService wxMaService; - private MemberFeignClient memberFeignClient; + private static final String ERROR_URI = "https://datatracker.ietf.org/doc/html/rfc6749#section-5.2"; - /** - * 微信认证 - * - * @param authentication - * @return - * @throws AuthenticationException - */ - @SneakyThrows - @Override - public Authentication authenticate(Authentication authentication) throws AuthenticationException { - WechatAuthenticationToken authenticationToken = (WechatAuthenticationToken) authentication; - String code = (String) authenticationToken.getPrincipal(); + private final AuthenticationManager authenticationManager; + private final OAuth2AuthorizationService authorizationService; + private final OAuth2TokenGenerator tokenGenerator; - WxMaJscode2SessionResult sessionInfo = wxMaService.getUserService().getSessionInfo(code); - String openid = sessionInfo.getOpenid(); - Result memberAuthResult = memberFeignClient.loadUserByOpenId(openid); - // 微信用户不存在,注册成为新会员 - if (memberAuthResult != null && ResultCode.USER_NOT_EXIST.getCode().equals(memberAuthResult.getCode())) { - - String sessionKey = sessionInfo.getSessionKey(); - String encryptedData = authenticationToken.getEncryptedData(); - String iv = authenticationToken.getIv(); - // 解密 encryptedData 获取用户信息 - WxMaUserInfo userInfo = wxMaService.getUserService().getUserInfo(sessionKey, encryptedData, iv); - - MemberDTO memberDTO = new MemberDTO(); - BeanUtil.copyProperties(userInfo, memberDTO); - memberDTO.setOpenid(openid); - memberFeignClient.addMember(memberDTO); + /** + * Constructs an {@code OAuth2ResourceOwnerPasswordAuthenticationProviderNew} using the provided parameters. + * + * @param authenticationManager the authentication manager + * @param authorizationService the authorization service + * @param tokenGenerator the token generator + * @since 0.2.3 + */ + public WechatAuthenticationProvider(AuthenticationManager authenticationManager, + OAuth2AuthorizationService authorizationService, + OAuth2TokenGenerator tokenGenerator + ) { + Assert.notNull(authorizationService, "authorizationService cannot be null"); + Assert.notNull(tokenGenerator, "tokenGenerator cannot be null"); + this.authenticationManager = authenticationManager; + this.authorizationService = authorizationService; + this.tokenGenerator = tokenGenerator; } - UserDetails userDetails = ((MemberUserDetailsServiceImpl) userDetailsService).loadUserByOpenId(openid); - WechatAuthenticationToken result = new WechatAuthenticationToken(userDetails, new HashSet<>()); - result.setDetails(authentication.getDetails()); - return result; - } + + @Override + public Authentication authenticate(Authentication authentication) throws AuthenticationException { + + ResourceOwnerPasswordAuthenticationToken authenticationToken = (ResourceOwnerPasswordAuthenticationToken) authentication; + + // 验证客户端是否已认证 + OAuth2ClientAuthenticationToken clientPrincipal = getAuthenticatedClientElseThrowInvalidClient(authenticationToken); + RegisteredClient registeredClient = clientPrincipal.getRegisteredClient(); + + // 验证客户端是否支持(grant_type=password)授权模式 + if (!registeredClient.getAuthorizationGrantTypes().contains(AuthorizationGrantType.PASSWORD)) { + throw new OAuth2AuthenticationException(OAuth2ErrorCodes.UNAUTHORIZED_CLIENT); + } + + // 密码验证 + Map additionalParameters = authenticationToken.getAdditionalParameters(); + String username = (String) additionalParameters.get("code"); + String encryptedData = (String) additionalParameters.get("encryptedData"); + String iv = (String) additionalParameters.get("iv"); + UsernamePasswordAuthenticationToken passwordAuthenticationToken = new UsernamePasswordAuthenticationToken(username, password); + log.debug("got usernamePasswordAuthenticationToken=" + passwordAuthenticationToken); + Authentication usernamePasswordAuthentication = authenticationManager.authenticate(passwordAuthenticationToken); + + usernamePasswordAuthentication.setAuthenticated(true); - @Override - public boolean supports(Class authentication) { - return WechatAuthenticationToken.class.isAssignableFrom(authentication); + + // 生成 access_token + // @formatter:off + DefaultOAuth2TokenContext.Builder tokenContextBuilder = DefaultOAuth2TokenContext.builder() + .registeredClient(registeredClient) + .principal(usernamePasswordAuthentication) + .authorizationServerContext(AuthorizationServerContextHolder.getContext()) + .authorizationGrantType(AuthorizationGrantType.PASSWORD) + .authorizationGrant(passwordAuthenticationToken); + // @formatter:on + + // ----- Access token ----- + OAuth2TokenContext tokenContext = tokenContextBuilder.tokenType(OAuth2TokenType.ACCESS_TOKEN).build(); + OAuth2Token generatedAccessToken = this.tokenGenerator.generate(tokenContext); + if (generatedAccessToken == null) { + OAuth2Error error = new OAuth2Error(OAuth2ErrorCodes.SERVER_ERROR, + "The token generator failed to generate the access token.", ERROR_URI); + throw new OAuth2AuthenticationException(error); + } + + OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, + generatedAccessToken.getTokenValue(), generatedAccessToken.getIssuedAt(), + generatedAccessToken.getExpiresAt(), tokenContext.getAuthorizedScopes()); + + // @formatter:off + OAuth2Authorization.Builder authorizationBuilder = OAuth2Authorization.withRegisteredClient(registeredClient) + .principalName(usernamePasswordAuthentication.getName()) + .authorizationGrantType(AuthorizationGrantType.PASSWORD) + .attribute(Principal.class.getName(), usernamePasswordAuthentication); + // @formatter:on + if (generatedAccessToken instanceof ClaimAccessor) { + authorizationBuilder.token(accessToken, (metadata) -> + metadata.put(OAuth2Authorization.Token.CLAIMS_METADATA_NAME, ((ClaimAccessor) generatedAccessToken).getClaims())); + } else { + authorizationBuilder.accessToken(accessToken); + } + + // ----- Refresh token ----- + OAuth2RefreshToken refreshToken = null; + if (registeredClient.getAuthorizationGrantTypes().contains(AuthorizationGrantType.REFRESH_TOKEN) && + // Do not issue refresh token to public client + !clientPrincipal.getClientAuthenticationMethod().equals(ClientAuthenticationMethod.NONE)) { + + tokenContext = tokenContextBuilder.tokenType(OAuth2TokenType.REFRESH_TOKEN).build(); + OAuth2Token generatedRefreshToken = this.tokenGenerator.generate(tokenContext); + if (!(generatedRefreshToken instanceof OAuth2RefreshToken)) { + OAuth2Error error = new OAuth2Error(OAuth2ErrorCodes.SERVER_ERROR, + "The token generator failed to generate the refresh token.", ERROR_URI); + throw new OAuth2AuthenticationException(error); + } + + + refreshToken = (OAuth2RefreshToken) generatedRefreshToken; + authorizationBuilder.refreshToken(refreshToken); + } + + OAuth2Authorization authorization = authorizationBuilder.build(); + this.authorizationService.save(authorization); + return new OAuth2AccessTokenAuthenticationToken(registeredClient, clientPrincipal, accessToken, refreshToken, additionalParameters); + } + + @Override + public boolean supports(Class authentication) { + return ResourceOwnerPasswordAuthenticationToken.class.isAssignableFrom(authentication); + } + + private static OAuth2ClientAuthenticationToken getAuthenticatedClientElseThrowInvalidClient(Authentication authentication) { + OAuth2ClientAuthenticationToken clientPrincipal = null; + if (OAuth2ClientAuthenticationToken.class.isAssignableFrom(authentication.getPrincipal().getClass())) { + clientPrincipal = (OAuth2ClientAuthenticationToken) authentication.getPrincipal(); + } + if (clientPrincipal != null && clientPrincipal.isAuthenticated()) { + return clientPrincipal; + } + throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_CLIENT); + } + } -} diff --git a/youlai-auth/src/main/java/com/youlai/auth/authentication/wechat/WechatAuthenticationToken.java b/youlai-auth/src/main/java/com/youlai/auth/authentication/wechat/WechatAuthenticationToken.java index ee5d715b8..48878f2ff 100644 --- a/youlai-auth/src/main/java/com/youlai/auth/authentication/wechat/WechatAuthenticationToken.java +++ b/youlai-auth/src/main/java/com/youlai/auth/authentication/wechat/WechatAuthenticationToken.java @@ -1,64 +1,51 @@ package com.youlai.auth.authentication.wechat; +import jakarta.annotation.Nullable; import lombok.Getter; import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.oauth2.core.AuthorizationGrantType; +import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; +import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationGrantAuthenticationToken; +import org.springframework.security.oauth2.server.authorization.util.SpringAuthorizationServerVersion; import org.springframework.util.Assert; -import java.util.Collection; +import java.util.*; /** - * @author haoxr - * @since 2021/9/25 + * 微信授权登录 + * + * @author haoxr + * @since 3.0.0 */ -public class WechatAuthenticationToken extends AbstractAuthenticationToken { - private static final long serialVersionUID = 550L; - private final Object principal; - @Getter - private String encryptedData; - @Getter - private String iv; - /** - * 账号校验之前的token构建 - * - * @param principal - */ - public WechatAuthenticationToken(Object principal, String encryptedData,String iv) { - super(null); - this.principal = principal; - this.encryptedData = encryptedData; - this.iv=iv; - setAuthenticated(false); - } +public class WechatAuthenticationToken extends OAuth2AuthorizationGrantAuthenticationToken { + + private final Set scopes; /** - * 账号校验成功之后的token构建 + * {@link org.springframework.security.oauth2.server.authorization.authentication.OAuth2ClientCredentialsAuthenticationToken} * - * @param principal - * @param authorities + * @param clientPrincipal + * @param additionalParameters */ - public WechatAuthenticationToken(Object principal, Collection authorities) { - super(authorities); - this.principal = principal; - super.setAuthenticated(true); + public WechatAuthenticationToken( + Authentication clientPrincipal, + @Nullable Set scopes, + Map additionalParameters + ) { + super(AuthorizationGrantType.PASSWORD, clientPrincipal, additionalParameters); + this.scopes = Collections.unmodifiableSet(scopes != null ? new HashSet<>(scopes) : Collections.emptySet()); + + } + + public Set getScopes() { + return this.scopes; } @Override public Object getCredentials() { - return null; + return this.getAdditionalParameters().get(OAuth2ParameterNames.PASSWORD); } - @Override - public Object getPrincipal() { - return this.principal; - } - - public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException { - Assert.isTrue(!isAuthenticated, "Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead"); - super.setAuthenticated(false); - } - - public void eraseCredentials() { - super.eraseCredentials(); - } } diff --git a/youlai-auth/src/main/java/com/youlai/auth/authentication/wechat/WechatTokenGranter.java b/youlai-auth/src/main/java/com/youlai/auth/authentication/wechat/WechatTokenGranter.java deleted file mode 100644 index 2af3fd0e4..000000000 --- a/youlai-auth/src/main/java/com/youlai/auth/authentication/wechat/WechatTokenGranter.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.youlai.auth.authentication.wechat; - -import org.springframework.security.authentication.*; -import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; -import org.springframework.security.oauth2.provider.*; -import org.springframework.security.oauth2.provider.token.AbstractTokenGranter; -import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; - -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * 微信授权者 - * - * @author haoxr - * @since 2021/9/25 - */ -public class WechatTokenGranter extends AbstractTokenGranter { - - /** - * 声明授权者 WechatTokenGranter 支持授权模式 wechat - * 根据接口传值 grant_type = wechat 的值匹配到此授权者 - * 匹配逻辑详见下面的两个方法 - * - * @see org.springframework.security.oauth2.provider.CompositeTokenGranter#grant(String, TokenRequest) - * @see org.springframework.security.oauth2.provider.token.AbstractTokenGranter#grant(String, TokenRequest) - */ - private static final String GRANT_TYPE = "wechat"; - private final AuthenticationManager authenticationManager; - - public WechatTokenGranter(AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory, AuthenticationManager authenticationManager) { - super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE); - this.authenticationManager = authenticationManager; - } - - @Override - protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) { - - Map parameters = new LinkedHashMap(tokenRequest.getRequestParameters()); - String code = parameters.get("code"); - String encryptedData = parameters.get("encryptedData"); - String iv = parameters.get("iv"); - - // 移除后续无用参数 - parameters.remove("code"); - parameters.remove("encryptedData"); - parameters.remove("iv"); - - Authentication userAuth = new WechatAuthenticationToken(code, encryptedData,iv); // 未认证状态 - ((AbstractAuthenticationToken) userAuth).setDetails(parameters); - - try { - userAuth = this.authenticationManager.authenticate(userAuth); // 认证中 - } catch (Exception e) { - throw new InvalidGrantException(e.getMessage()); - } - - if (userAuth != null && userAuth.isAuthenticated()) { // 认证成功 - OAuth2Request storedOAuth2Request = this.getRequestFactory().createOAuth2Request(client, tokenRequest); - return new OAuth2Authentication(storedOAuth2Request, userAuth); - } else { // 认证失败 - throw new InvalidGrantException("Could not authenticate code: " + code); - } - } -}