mirror of
https://gitee.com/youlaitech/youlai-mall.git
synced 2024-12-22 12:48:59 +08:00
refactor: 认证中心升级(临时提交勿clone)
This commit is contained in:
parent
b019e6dda6
commit
84aa6da775
@ -98,7 +98,7 @@ public class ResourceOwnerPasswordAuthenticationProvider implements Authenticati
|
||||
}
|
||||
|
||||
// 生成 access_token
|
||||
// @formatter:off
|
||||
// @formatter:off
|
||||
DefaultOAuth2TokenContext.Builder tokenContextBuilder = DefaultOAuth2TokenContext.builder()
|
||||
.registeredClient(registeredClient)
|
||||
.principal(usernamePasswordAuthentication)
|
||||
|
@ -18,7 +18,7 @@ public class ResourceOwnerPasswordAuthenticationToken extends OAuth2Authorizatio
|
||||
* @param clientPrincipal
|
||||
* @param additionalParameters
|
||||
*/
|
||||
protected ResourceOwnerPasswordAuthenticationToken(
|
||||
public ResourceOwnerPasswordAuthenticationToken(
|
||||
Authentication clientPrincipal,
|
||||
@Nullable Set<String> scopes,
|
||||
Map<String, Object> additionalParameters
|
||||
|
@ -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<String, String> 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<String> 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<String, Object> 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<String, String> getParameters(HttpServletRequest request) {
|
||||
Map<String, String[]> parameterMap = request.getParameterMap();
|
||||
MultiValueMap<String, String> 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);
|
||||
}
|
||||
|
||||
}
|
@ -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 <a href="mailto:xianrui0365@163.com">haoxr</a>
|
||||
* @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";
|
||||
|
||||
private final AuthenticationManager authenticationManager;
|
||||
private final OAuth2AuthorizationService authorizationService;
|
||||
private final OAuth2TokenGenerator<? extends OAuth2Token> tokenGenerator;
|
||||
|
||||
/**
|
||||
* 微信认证
|
||||
* Constructs an {@code OAuth2ResourceOwnerPasswordAuthenticationProviderNew} using the provided parameters.
|
||||
*
|
||||
* @param authentication
|
||||
* @return
|
||||
* @throws AuthenticationException
|
||||
* @param authenticationManager the authentication manager
|
||||
* @param authorizationService the authorization service
|
||||
* @param tokenGenerator the token generator
|
||||
* @since 0.2.3
|
||||
*/
|
||||
@SneakyThrows
|
||||
public WechatAuthenticationProvider(AuthenticationManager authenticationManager,
|
||||
OAuth2AuthorizationService authorizationService,
|
||||
OAuth2TokenGenerator<? extends OAuth2Token> tokenGenerator
|
||||
) {
|
||||
Assert.notNull(authorizationService, "authorizationService cannot be null");
|
||||
Assert.notNull(tokenGenerator, "tokenGenerator cannot be null");
|
||||
this.authenticationManager = authenticationManager;
|
||||
this.authorizationService = authorizationService;
|
||||
this.tokenGenerator = tokenGenerator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||
WechatAuthenticationToken authenticationToken = (WechatAuthenticationToken) authentication;
|
||||
String code = (String) authenticationToken.getPrincipal();
|
||||
|
||||
WxMaJscode2SessionResult sessionInfo = wxMaService.getUserService().getSessionInfo(code);
|
||||
String openid = sessionInfo.getOpenid();
|
||||
Result<MemberAuthDTO> memberAuthResult = memberFeignClient.loadUserByOpenId(openid);
|
||||
// 微信用户不存在,注册成为新会员
|
||||
if (memberAuthResult != null && ResultCode.USER_NOT_EXIST.getCode().equals(memberAuthResult.getCode())) {
|
||||
ResourceOwnerPasswordAuthenticationToken authenticationToken = (ResourceOwnerPasswordAuthenticationToken) authentication;
|
||||
|
||||
String sessionKey = sessionInfo.getSessionKey();
|
||||
String encryptedData = authenticationToken.getEncryptedData();
|
||||
String iv = authenticationToken.getIv();
|
||||
// 解密 encryptedData 获取用户信息
|
||||
WxMaUserInfo userInfo = wxMaService.getUserService().getUserInfo(sessionKey, encryptedData, iv);
|
||||
// 验证客户端是否已认证
|
||||
OAuth2ClientAuthenticationToken clientPrincipal = getAuthenticatedClientElseThrowInvalidClient(authenticationToken);
|
||||
RegisteredClient registeredClient = clientPrincipal.getRegisteredClient();
|
||||
|
||||
MemberDTO memberDTO = new MemberDTO();
|
||||
BeanUtil.copyProperties(userInfo, memberDTO);
|
||||
memberDTO.setOpenid(openid);
|
||||
memberFeignClient.addMember(memberDTO);
|
||||
}
|
||||
UserDetails userDetails = ((MemberUserDetailsServiceImpl) userDetailsService).loadUserByOpenId(openid);
|
||||
WechatAuthenticationToken result = new WechatAuthenticationToken(userDetails, new HashSet<>());
|
||||
result.setDetails(authentication.getDetails());
|
||||
return result;
|
||||
// 验证客户端是否支持(grant_type=password)授权模式
|
||||
if (!registeredClient.getAuthorizationGrantTypes().contains(AuthorizationGrantType.PASSWORD)) {
|
||||
throw new OAuth2AuthenticationException(OAuth2ErrorCodes.UNAUTHORIZED_CLIENT);
|
||||
}
|
||||
|
||||
// 密码验证
|
||||
Map<String, Object> 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);
|
||||
|
||||
|
||||
|
||||
// 生成 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 WechatAuthenticationToken.class.isAssignableFrom(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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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 <a href="mailto:xianrui0365@163.com">haoxr</a>
|
||||
* @since 2021/9/25
|
||||
*/
|
||||
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
|
||||
* @author haoxr
|
||||
* @since 3.0.0
|
||||
*/
|
||||
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<String> scopes;
|
||||
|
||||
/**
|
||||
* 账号校验成功之后的token构建
|
||||
* {@link org.springframework.security.oauth2.server.authorization.authentication.OAuth2ClientCredentialsAuthenticationToken}
|
||||
*
|
||||
* @param principal
|
||||
* @param authorities
|
||||
* @param clientPrincipal
|
||||
* @param additionalParameters
|
||||
*/
|
||||
public WechatAuthenticationToken(Object principal, Collection<? extends GrantedAuthority> authorities) {
|
||||
super(authorities);
|
||||
this.principal = principal;
|
||||
super.setAuthenticated(true);
|
||||
public WechatAuthenticationToken(
|
||||
Authentication clientPrincipal,
|
||||
@Nullable Set<String> scopes,
|
||||
Map<String, Object> additionalParameters
|
||||
) {
|
||||
super(AuthorizationGrantType.PASSWORD, clientPrincipal, additionalParameters);
|
||||
this.scopes = Collections.unmodifiableSet(scopes != null ? new HashSet<>(scopes) : Collections.emptySet());
|
||||
|
||||
}
|
||||
|
||||
public Set<String> 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();
|
||||
}
|
||||
}
|
||||
|
@ -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 <a href="mailto:xianrui0365@163.com">haoxr</a>
|
||||
* @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<String, String> 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);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user