mirror of
https://gitee.com/youlaitech/youlai-mall.git
synced 2024-12-22 12:48:59 +08:00
refactor: 优化oauth2授权扩展
This commit is contained in:
parent
09359627a0
commit
a1c68b15dc
@ -14,14 +14,14 @@ import com.nimbusds.jose.proc.SecurityContext;
|
|||||||
import com.youlai.auth.model.SysUserDetails;
|
import com.youlai.auth.model.SysUserDetails;
|
||||||
import com.youlai.auth.oauth2.extension.captcha.CaptchaAuthenticationConverter;
|
import com.youlai.auth.oauth2.extension.captcha.CaptchaAuthenticationConverter;
|
||||||
import com.youlai.auth.oauth2.extension.captcha.CaptchaAuthenticationProvider;
|
import com.youlai.auth.oauth2.extension.captcha.CaptchaAuthenticationProvider;
|
||||||
import com.youlai.auth.oauth2.extension.miniapp.WxMiniAppAuthenticationConverter;
|
import com.youlai.auth.oauth2.extension.wechat.WechatAuthenticationConverter;
|
||||||
import com.youlai.auth.oauth2.extension.miniapp.WxMiniAppAuthenticationProvider;
|
import com.youlai.auth.oauth2.extension.wechat.WechatAuthenticationProvider;
|
||||||
import com.youlai.auth.oauth2.extension.miniapp.WxMiniAppAuthenticationToken;
|
import com.youlai.auth.oauth2.extension.wechat.WechatAuthenticationToken;
|
||||||
import com.youlai.auth.oauth2.extension.password.PasswordAuthenticationConverter;
|
import com.youlai.auth.oauth2.extension.password.PasswordAuthenticationConverter;
|
||||||
import com.youlai.auth.oauth2.extension.password.PasswordAuthenticationProvider;
|
import com.youlai.auth.oauth2.extension.password.PasswordAuthenticationProvider;
|
||||||
import com.youlai.auth.oauth2.extension.sms.SmsAuthenticationConverter;
|
import com.youlai.auth.oauth2.extension.smscode.SmsCodeAuthenticationConverter;
|
||||||
import com.youlai.auth.oauth2.extension.sms.SmsAuthenticationProvider;
|
import com.youlai.auth.oauth2.extension.smscode.SmsCodeAuthenticationProvider;
|
||||||
import com.youlai.auth.oauth2.extension.sms.SmsAuthenticationToken;
|
import com.youlai.auth.oauth2.extension.smscode.SmsCodeAuthenticationToken;
|
||||||
import com.youlai.auth.oauth2.handler.MyAuthenticationFailureHandler;
|
import com.youlai.auth.oauth2.handler.MyAuthenticationFailureHandler;
|
||||||
import com.youlai.auth.oauth2.handler.MyAuthenticationSuccessHandler;
|
import com.youlai.auth.oauth2.handler.MyAuthenticationSuccessHandler;
|
||||||
import com.youlai.auth.oauth2.jackson.SysUserMixin;
|
import com.youlai.auth.oauth2.jackson.SysUserMixin;
|
||||||
@ -96,8 +96,6 @@ public class AuthorizationServerConfig {
|
|||||||
private final CustomOidcUserInfoService customOidcUserInfoService;
|
private final CustomOidcUserInfoService customOidcUserInfoService;
|
||||||
|
|
||||||
private final OAuth2TokenCustomizer<JwtEncodingContext> jwtCustomizer;
|
private final OAuth2TokenCustomizer<JwtEncodingContext> jwtCustomizer;
|
||||||
private static final String CUSTOM_CONSENT_PAGE_URI = "/oauth2/consent"; // 自定义授权页
|
|
||||||
private static final String CUSTOM_LOGIN_PAGE_URI = "/sso-login"; // 自定义登录页
|
|
||||||
|
|
||||||
private final StringRedisTemplate redisTemplate;
|
private final StringRedisTemplate redisTemplate;
|
||||||
|
|
||||||
@ -119,8 +117,6 @@ public class AuthorizationServerConfig {
|
|||||||
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
|
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
|
||||||
|
|
||||||
http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
|
http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
|
||||||
.authorizationEndpoint(authorizationEndpoint -> authorizationEndpoint.consentPage(CUSTOM_CONSENT_PAGE_URI)) // 自定义授权页
|
|
||||||
|
|
||||||
// 自定义授权模式转换器(Converter)
|
// 自定义授权模式转换器(Converter)
|
||||||
.tokenEndpoint(tokenEndpoint -> tokenEndpoint
|
.tokenEndpoint(tokenEndpoint -> tokenEndpoint
|
||||||
.accessTokenRequestConverters(
|
.accessTokenRequestConverters(
|
||||||
@ -130,8 +126,8 @@ public class AuthorizationServerConfig {
|
|||||||
List.of(
|
List.of(
|
||||||
new PasswordAuthenticationConverter(),
|
new PasswordAuthenticationConverter(),
|
||||||
new CaptchaAuthenticationConverter(),
|
new CaptchaAuthenticationConverter(),
|
||||||
new WxMiniAppAuthenticationConverter(),
|
new WechatAuthenticationConverter(),
|
||||||
new SmsAuthenticationConverter()
|
new SmsCodeAuthenticationConverter()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -142,8 +138,8 @@ public class AuthorizationServerConfig {
|
|||||||
List.of(
|
List.of(
|
||||||
new PasswordAuthenticationProvider(authenticationManager, authorizationService, tokenGenerator),
|
new PasswordAuthenticationProvider(authenticationManager, authorizationService, tokenGenerator),
|
||||||
new CaptchaAuthenticationProvider(authenticationManager, authorizationService, tokenGenerator, redisTemplate, codeGenerator),
|
new CaptchaAuthenticationProvider(authenticationManager, authorizationService, tokenGenerator, redisTemplate, codeGenerator),
|
||||||
new WxMiniAppAuthenticationProvider(authorizationService, tokenGenerator, memberDetailsService, wxMaService),
|
new WechatAuthenticationProvider(authorizationService, tokenGenerator, memberDetailsService, wxMaService),
|
||||||
new SmsAuthenticationProvider(authorizationService, tokenGenerator, memberDetailsService, redisTemplate)
|
new SmsCodeAuthenticationProvider(authorizationService, tokenGenerator, memberDetailsService, redisTemplate)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -161,17 +157,14 @@ public class AuthorizationServerConfig {
|
|||||||
);
|
);
|
||||||
|
|
||||||
http
|
http
|
||||||
// 当用户未登录且尝试访问需要认证的端点时,重定向至登录页面
|
|
||||||
.exceptionHandling((exceptions) -> exceptions
|
.exceptionHandling((exceptions) -> exceptions
|
||||||
.defaultAuthenticationEntryPointFor(
|
.defaultAuthenticationEntryPointFor(
|
||||||
new LoginUrlAuthenticationEntryPoint(CUSTOM_LOGIN_PAGE_URI),
|
new LoginUrlAuthenticationEntryPoint("/login"),
|
||||||
new MediaTypeRequestMatcher(MediaType.TEXT_HTML)
|
new MediaTypeRequestMatcher(MediaType.TEXT_HTML)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
// Accept access tokens for User Info and/or Client Registration
|
|
||||||
.oauth2ResourceServer(oauth2ResourceServer ->
|
.oauth2ResourceServer(oauth2ResourceServer ->
|
||||||
oauth2ResourceServer.jwt(Customizer.withDefaults()));
|
oauth2ResourceServer.jwt(Customizer.withDefaults()));
|
||||||
|
|
||||||
return http.build();
|
return http.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -374,8 +367,8 @@ public class AuthorizationServerConfig {
|
|||||||
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
|
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
|
||||||
.authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
|
.authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
|
||||||
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
|
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
|
||||||
.authorizationGrantType(WxMiniAppAuthenticationToken.WECHAT_MINI_APP) // 微信小程序模式
|
.authorizationGrantType(WechatAuthenticationToken.WECHAT_MINI_APP) // 微信小程序模式
|
||||||
.authorizationGrantType(SmsAuthenticationToken.SMS_CODE) // 短信验证码模式
|
.authorizationGrantType(SmsCodeAuthenticationToken.SMS_CODE) // 短信验证码模式
|
||||||
.redirectUri("http://127.0.0.1:8080/authorized")
|
.redirectUri("http://127.0.0.1:8080/authorized")
|
||||||
.postLogoutRedirectUri("http://127.0.0.1:8080/logged-out")
|
.postLogoutRedirectUri("http://127.0.0.1:8080/logged-out")
|
||||||
.scope(OidcScopes.OPENID)
|
.scope(OidcScopes.OPENID)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package com.youlai.auth.oauth2.extension.sms;
|
package com.youlai.auth.oauth2.extension.smscode;
|
||||||
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.youlai.auth.util.OAuth2EndpointUtils;
|
import com.youlai.auth.util.OAuth2EndpointUtils;
|
||||||
@ -26,13 +26,13 @@ import java.util.stream.Collectors;
|
|||||||
* @see org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2AuthorizationCodeAuthenticationConverter
|
* @see org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2AuthorizationCodeAuthenticationConverter
|
||||||
* @since 3.0.0
|
* @since 3.0.0
|
||||||
*/
|
*/
|
||||||
public class SmsAuthenticationConverter implements AuthenticationConverter {
|
public class SmsCodeAuthenticationConverter implements AuthenticationConverter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Authentication convert(HttpServletRequest request) {
|
public Authentication convert(HttpServletRequest request) {
|
||||||
// 授权类型 (必需)
|
// 授权类型 (必需)
|
||||||
String grantType = request.getParameter(OAuth2ParameterNames.GRANT_TYPE);
|
String grantType = request.getParameter(OAuth2ParameterNames.GRANT_TYPE);
|
||||||
if (!SmsAuthenticationToken.SMS_CODE.getValue().equals(grantType)) {
|
if (!SmsCodeAuthenticationToken.SMS_CODE.getValue().equals(grantType)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,20 +57,20 @@ public class SmsAuthenticationConverter implements AuthenticationConverter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 手机号(必需)
|
// 手机号(必需)
|
||||||
String mobile = parameters.getFirst(SmsParameterNames.MOBILE);
|
String mobile = parameters.getFirst(SmsCodeParameterNames.MOBILE);
|
||||||
if (StrUtil.isBlank(mobile)) {
|
if (StrUtil.isBlank(mobile)) {
|
||||||
OAuth2EndpointUtils.throwError(
|
OAuth2EndpointUtils.throwError(
|
||||||
OAuth2ErrorCodes.INVALID_REQUEST,
|
OAuth2ErrorCodes.INVALID_REQUEST,
|
||||||
SmsParameterNames.MOBILE,
|
SmsCodeParameterNames.MOBILE,
|
||||||
OAuth2EndpointUtils.ACCESS_TOKEN_REQUEST_ERROR_URI);
|
OAuth2EndpointUtils.ACCESS_TOKEN_REQUEST_ERROR_URI);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 验证码(必需)
|
// 验证码(必需)
|
||||||
String code = parameters.getFirst(SmsParameterNames.CODE);
|
String code = parameters.getFirst(SmsCodeParameterNames.CODE);
|
||||||
if (StrUtil.isBlank(code)) {
|
if (StrUtil.isBlank(code)) {
|
||||||
OAuth2EndpointUtils.throwError(
|
OAuth2EndpointUtils.throwError(
|
||||||
OAuth2ErrorCodes.INVALID_REQUEST,
|
OAuth2ErrorCodes.INVALID_REQUEST,
|
||||||
SmsParameterNames.CODE,
|
SmsCodeParameterNames.CODE,
|
||||||
OAuth2EndpointUtils.ACCESS_TOKEN_REQUEST_ERROR_URI);
|
OAuth2EndpointUtils.ACCESS_TOKEN_REQUEST_ERROR_URI);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,7 +85,7 @@ public class SmsAuthenticationConverter implements AuthenticationConverter {
|
|||||||
)
|
)
|
||||||
.collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().get(0)));
|
.collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().get(0)));
|
||||||
|
|
||||||
return new SmsAuthenticationToken(
|
return new SmsCodeAuthenticationToken(
|
||||||
clientPrincipal,
|
clientPrincipal,
|
||||||
requestedScopes,
|
requestedScopes,
|
||||||
additionalParameters
|
additionalParameters
|
@ -1,4 +1,4 @@
|
|||||||
package com.youlai.auth.oauth2.extension.sms;
|
package com.youlai.auth.oauth2.extension.smscode;
|
||||||
|
|
||||||
import cn.hutool.core.lang.Assert;
|
import cn.hutool.core.lang.Assert;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
@ -34,7 +34,7 @@ import java.util.Map;
|
|||||||
* @since 3.0.0
|
* @since 3.0.0
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class SmsAuthenticationProvider implements AuthenticationProvider {
|
public class SmsCodeAuthenticationProvider implements AuthenticationProvider {
|
||||||
|
|
||||||
private static final String ERROR_URI = "https://datatracker.ietf.org/doc/html/rfc6749#section-5.2";
|
private static final String ERROR_URI = "https://datatracker.ietf.org/doc/html/rfc6749#section-5.2";
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ public class SmsAuthenticationProvider implements AuthenticationProvider {
|
|||||||
* @param tokenGenerator the token generator
|
* @param tokenGenerator the token generator
|
||||||
* @since 0.2.3
|
* @since 0.2.3
|
||||||
*/
|
*/
|
||||||
public SmsAuthenticationProvider(
|
public SmsCodeAuthenticationProvider(
|
||||||
OAuth2AuthorizationService authorizationService,
|
OAuth2AuthorizationService authorizationService,
|
||||||
OAuth2TokenGenerator<? extends OAuth2Token> tokenGenerator,
|
OAuth2TokenGenerator<? extends OAuth2Token> tokenGenerator,
|
||||||
MemberDetailsService memberDetailsService,
|
MemberDetailsService memberDetailsService,
|
||||||
@ -72,21 +72,21 @@ public class SmsAuthenticationProvider implements AuthenticationProvider {
|
|||||||
@Override
|
@Override
|
||||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||||
|
|
||||||
SmsAuthenticationToken smsAuthenticationToken = (SmsAuthenticationToken) authentication;
|
SmsCodeAuthenticationToken smsCodeAuthenticationToken = (SmsCodeAuthenticationToken) authentication;
|
||||||
|
|
||||||
OAuth2ClientAuthenticationToken clientPrincipal = OAuth2AuthenticationProviderUtils
|
OAuth2ClientAuthenticationToken clientPrincipal = OAuth2AuthenticationProviderUtils
|
||||||
.getAuthenticatedClientElseThrowInvalidClient(smsAuthenticationToken);
|
.getAuthenticatedClientElseThrowInvalidClient(smsCodeAuthenticationToken);
|
||||||
RegisteredClient registeredClient = clientPrincipal.getRegisteredClient();
|
RegisteredClient registeredClient = clientPrincipal.getRegisteredClient();
|
||||||
|
|
||||||
// 验证客户端是否支持授权类型(grant_type=wechat_mini_app)
|
// 验证客户端是否支持授权类型(grant_type=wechat_mini_app)
|
||||||
if (!registeredClient.getAuthorizationGrantTypes().contains(SmsAuthenticationToken.SMS_CODE)) {
|
if (!registeredClient.getAuthorizationGrantTypes().contains(SmsCodeAuthenticationToken.SMS_CODE)) {
|
||||||
throw new OAuth2AuthenticationException(OAuth2ErrorCodes.UNAUTHORIZED_CLIENT);
|
throw new OAuth2AuthenticationException(OAuth2ErrorCodes.UNAUTHORIZED_CLIENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 短信验证码校验
|
// 短信验证码校验
|
||||||
Map<String, Object> additionalParameters = smsAuthenticationToken.getAdditionalParameters();
|
Map<String, Object> additionalParameters = smsCodeAuthenticationToken.getAdditionalParameters();
|
||||||
String mobile = (String) additionalParameters.get(SmsParameterNames.MOBILE);
|
String mobile = (String) additionalParameters.get(SmsCodeParameterNames.MOBILE);
|
||||||
String code = (String) additionalParameters.get(SmsParameterNames.CODE);
|
String code = (String) additionalParameters.get(SmsCodeParameterNames.CODE);
|
||||||
|
|
||||||
if (!code.equals("666666")) { // 666666 是后门,因为短信收费,正式环境删除这个if
|
if (!code.equals("666666")) { // 666666 是后门,因为短信收费,正式环境删除这个if
|
||||||
String codeKey = RedisConstants.LOGIN_SMS_CODE_PREFIX + mobile;
|
String codeKey = RedisConstants.LOGIN_SMS_CODE_PREFIX + mobile;
|
||||||
@ -107,8 +107,8 @@ public class SmsAuthenticationProvider implements AuthenticationProvider {
|
|||||||
.registeredClient(registeredClient)
|
.registeredClient(registeredClient)
|
||||||
.principal(usernamePasswordAuthentication)
|
.principal(usernamePasswordAuthentication)
|
||||||
.authorizationServerContext(AuthorizationServerContextHolder.getContext())
|
.authorizationServerContext(AuthorizationServerContextHolder.getContext())
|
||||||
.authorizationGrantType(SmsAuthenticationToken.SMS_CODE)
|
.authorizationGrantType(SmsCodeAuthenticationToken.SMS_CODE)
|
||||||
.authorizationGrant(smsAuthenticationToken);
|
.authorizationGrant(smsCodeAuthenticationToken);
|
||||||
|
|
||||||
// 生成访问令牌(Access Token)
|
// 生成访问令牌(Access Token)
|
||||||
OAuth2TokenContext tokenContext = tokenContextBuilder.tokenType(OAuth2TokenType.ACCESS_TOKEN).build();
|
OAuth2TokenContext tokenContext = tokenContextBuilder.tokenType(OAuth2TokenType.ACCESS_TOKEN).build();
|
||||||
@ -124,7 +124,7 @@ public class SmsAuthenticationProvider implements AuthenticationProvider {
|
|||||||
generatedAccessToken.getExpiresAt(), tokenContext.getAuthorizedScopes());
|
generatedAccessToken.getExpiresAt(), tokenContext.getAuthorizedScopes());
|
||||||
OAuth2Authorization.Builder authorizationBuilder = OAuth2Authorization.withRegisteredClient(registeredClient)
|
OAuth2Authorization.Builder authorizationBuilder = OAuth2Authorization.withRegisteredClient(registeredClient)
|
||||||
.principalName(userDetails.getUsername())
|
.principalName(userDetails.getUsername())
|
||||||
.authorizationGrantType(SmsAuthenticationToken.SMS_CODE)
|
.authorizationGrantType(SmsCodeAuthenticationToken.SMS_CODE)
|
||||||
.attribute(Principal.class.getName(), usernamePasswordAuthentication);
|
.attribute(Principal.class.getName(), usernamePasswordAuthentication);
|
||||||
if (generatedAccessToken instanceof ClaimAccessor) {
|
if (generatedAccessToken instanceof ClaimAccessor) {
|
||||||
authorizationBuilder.token(accessToken, (metadata) ->
|
authorizationBuilder.token(accessToken, (metadata) ->
|
||||||
@ -159,7 +159,7 @@ public class SmsAuthenticationProvider implements AuthenticationProvider {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean supports(Class<?> authentication) {
|
public boolean supports(Class<?> authentication) {
|
||||||
return SmsAuthenticationToken.class.isAssignableFrom(authentication);
|
return SmsCodeAuthenticationToken.class.isAssignableFrom(authentication);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package com.youlai.auth.oauth2.extension.sms;
|
package com.youlai.auth.oauth2.extension.smscode;
|
||||||
|
|
||||||
import jakarta.annotation.Nullable;
|
import jakarta.annotation.Nullable;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
@ -14,10 +14,10 @@ import java.util.Set;
|
|||||||
/**
|
/**
|
||||||
* 短信验证码身份验证令牌
|
* 短信验证码身份验证令牌
|
||||||
*
|
*
|
||||||
* @author haoxr
|
* @author Ray Hao
|
||||||
* @since 3.0.0
|
* @since 3.0.0
|
||||||
*/
|
*/
|
||||||
public class SmsAuthenticationToken extends OAuth2AuthorizationGrantAuthenticationToken {
|
public class SmsCodeAuthenticationToken extends OAuth2AuthorizationGrantAuthenticationToken {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 令牌申请访问范围
|
* 令牌申请访问范围
|
||||||
@ -27,15 +27,15 @@ public class SmsAuthenticationToken extends OAuth2AuthorizationGrantAuthenticati
|
|||||||
/**
|
/**
|
||||||
* 授权类型(短信验证码: sms_code)
|
* 授权类型(短信验证码: sms_code)
|
||||||
*/
|
*/
|
||||||
public static final AuthorizationGrantType SMS_CODE = new AuthorizationGrantType("sms");
|
public static final AuthorizationGrantType SMS_CODE = new AuthorizationGrantType("sms_code");
|
||||||
|
|
||||||
|
|
||||||
protected SmsAuthenticationToken(
|
protected SmsCodeAuthenticationToken(
|
||||||
Authentication clientPrincipal,
|
Authentication clientPrincipal,
|
||||||
Set<String> scopes,
|
Set<String> scopes,
|
||||||
@Nullable Map<String, Object> additionalParameters
|
@Nullable Map<String, Object> additionalParameters
|
||||||
) {
|
) {
|
||||||
super(SmsAuthenticationToken.SMS_CODE, clientPrincipal, additionalParameters);
|
super(SmsCodeAuthenticationToken.SMS_CODE, clientPrincipal, additionalParameters);
|
||||||
this.scopes = Collections.unmodifiableSet(scopes != null ? new HashSet<>(scopes) : Collections.emptySet());
|
this.scopes = Collections.unmodifiableSet(scopes != null ? new HashSet<>(scopes) : Collections.emptySet());
|
||||||
}
|
}
|
||||||
|
|
@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.youlai.auth.oauth2.extension.sms;
|
package com.youlai.auth.oauth2.extension.smscode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 短信验证码模式参数名称常量
|
* 短信验证码模式参数名称常量
|
||||||
@ -22,7 +22,7 @@ package com.youlai.auth.oauth2.extension.sms;
|
|||||||
* @author haoxr
|
* @author haoxr
|
||||||
* @since 3.0.0
|
* @since 3.0.0
|
||||||
*/
|
*/
|
||||||
public final class SmsParameterNames {
|
public final class SmsCodeParameterNames {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 手机号
|
* 手机号
|
||||||
@ -35,7 +35,7 @@ public final class SmsParameterNames {
|
|||||||
public static final String CODE = "code";
|
public static final String CODE = "code";
|
||||||
|
|
||||||
|
|
||||||
private SmsParameterNames() {
|
private SmsCodeParameterNames() {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package com.youlai.auth.oauth2.extension.miniapp;
|
package com.youlai.auth.oauth2.extension.wechat;
|
||||||
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.youlai.auth.util.OAuth2EndpointUtils;
|
import com.youlai.auth.util.OAuth2EndpointUtils;
|
||||||
@ -26,7 +26,7 @@ import java.util.stream.Collectors;
|
|||||||
* @see org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2AuthorizationCodeAuthenticationConverter
|
* @see org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2AuthorizationCodeAuthenticationConverter
|
||||||
* @since 3.0.0
|
* @since 3.0.0
|
||||||
*/
|
*/
|
||||||
public class WxMiniAppAuthenticationConverter implements AuthenticationConverter {
|
public class WechatAuthenticationConverter implements AuthenticationConverter {
|
||||||
|
|
||||||
public static final String ACCESS_TOKEN_REQUEST_ERROR_URI = "https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html";
|
public static final String ACCESS_TOKEN_REQUEST_ERROR_URI = "https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html";
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ public class WxMiniAppAuthenticationConverter implements AuthenticationConverter
|
|||||||
public Authentication convert(HttpServletRequest request) {
|
public Authentication convert(HttpServletRequest request) {
|
||||||
// 授权类型 (必需)
|
// 授权类型 (必需)
|
||||||
String grantType = request.getParameter(OAuth2ParameterNames.GRANT_TYPE);
|
String grantType = request.getParameter(OAuth2ParameterNames.GRANT_TYPE);
|
||||||
if (!WxMiniAppAuthenticationToken.WECHAT_MINI_APP.getValue().equals(grantType)) {
|
if (!WechatAuthenticationToken.WECHAT_MINI_APP.getValue().equals(grantType)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ public class WxMiniAppAuthenticationConverter implements AuthenticationConverter
|
|||||||
)
|
)
|
||||||
.collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().get(0)));
|
.collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().get(0)));
|
||||||
|
|
||||||
return new WxMiniAppAuthenticationToken(
|
return new WechatAuthenticationToken(
|
||||||
clientPrincipal,
|
clientPrincipal,
|
||||||
requestedScopes,
|
requestedScopes,
|
||||||
additionalParameters
|
additionalParameters
|
@ -1,4 +1,4 @@
|
|||||||
package com.youlai.auth.oauth2.extension.miniapp;
|
package com.youlai.auth.oauth2.extension.wechat;
|
||||||
|
|
||||||
import cn.binarywang.wx.miniapp.api.WxMaService;
|
import cn.binarywang.wx.miniapp.api.WxMaService;
|
||||||
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
|
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
|
||||||
@ -35,7 +35,7 @@ import java.util.Map;
|
|||||||
* @since 3.0.0
|
* @since 3.0.0
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class WxMiniAppAuthenticationProvider implements AuthenticationProvider {
|
public class WechatAuthenticationProvider implements AuthenticationProvider {
|
||||||
|
|
||||||
private static final String ERROR_URI = "https://datatracker.ietf.org/doc/html/rfc6749#section-5.2";
|
private static final String ERROR_URI = "https://datatracker.ietf.org/doc/html/rfc6749#section-5.2";
|
||||||
|
|
||||||
@ -54,7 +54,7 @@ public class WxMiniAppAuthenticationProvider implements AuthenticationProvider {
|
|||||||
* @param tokenGenerator the token generator
|
* @param tokenGenerator the token generator
|
||||||
* @since 0.2.3
|
* @since 0.2.3
|
||||||
*/
|
*/
|
||||||
public WxMiniAppAuthenticationProvider(
|
public WechatAuthenticationProvider(
|
||||||
OAuth2AuthorizationService authorizationService,
|
OAuth2AuthorizationService authorizationService,
|
||||||
OAuth2TokenGenerator<? extends OAuth2Token> tokenGenerator,
|
OAuth2TokenGenerator<? extends OAuth2Token> tokenGenerator,
|
||||||
MemberDetailsService memberDetailsService,
|
MemberDetailsService memberDetailsService,
|
||||||
@ -74,19 +74,19 @@ public class WxMiniAppAuthenticationProvider implements AuthenticationProvider {
|
|||||||
@Override
|
@Override
|
||||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||||
|
|
||||||
WxMiniAppAuthenticationToken wxMiniAppAuthenticationToken = (WxMiniAppAuthenticationToken) authentication;
|
WechatAuthenticationToken wechatAuthenticationToken = (WechatAuthenticationToken) authentication;
|
||||||
|
|
||||||
OAuth2ClientAuthenticationToken clientPrincipal = OAuth2AuthenticationProviderUtils
|
OAuth2ClientAuthenticationToken clientPrincipal = OAuth2AuthenticationProviderUtils
|
||||||
.getAuthenticatedClientElseThrowInvalidClient(wxMiniAppAuthenticationToken);
|
.getAuthenticatedClientElseThrowInvalidClient(wechatAuthenticationToken);
|
||||||
RegisteredClient registeredClient = clientPrincipal.getRegisteredClient();
|
RegisteredClient registeredClient = clientPrincipal.getRegisteredClient();
|
||||||
|
|
||||||
// 验证客户端是否支持授权类型(grant_type=wechat_mini_app)
|
// 验证客户端是否支持授权类型(grant_type=wechat_mini_app)
|
||||||
if (!registeredClient.getAuthorizationGrantTypes().contains(WxMiniAppAuthenticationToken.WECHAT_MINI_APP)) {
|
if (!registeredClient.getAuthorizationGrantTypes().contains(WechatAuthenticationToken.WECHAT_MINI_APP)) {
|
||||||
throw new OAuth2AuthenticationException(OAuth2ErrorCodes.UNAUTHORIZED_CLIENT);
|
throw new OAuth2AuthenticationException(OAuth2ErrorCodes.UNAUTHORIZED_CLIENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 微信 code 获取 openid
|
// 微信 code 获取 openid
|
||||||
Map<String, Object> additionalParameters = wxMiniAppAuthenticationToken.getAdditionalParameters();
|
Map<String, Object> additionalParameters = wechatAuthenticationToken.getAdditionalParameters();
|
||||||
String code = (String) additionalParameters.get(OAuth2ParameterNames.CODE);
|
String code = (String) additionalParameters.get(OAuth2ParameterNames.CODE);
|
||||||
WxMaJscode2SessionResult sessionInfo;
|
WxMaJscode2SessionResult sessionInfo;
|
||||||
try {
|
try {
|
||||||
@ -106,8 +106,8 @@ public class WxMiniAppAuthenticationProvider implements AuthenticationProvider {
|
|||||||
.registeredClient(registeredClient)
|
.registeredClient(registeredClient)
|
||||||
.principal(usernamePasswordAuthentication)
|
.principal(usernamePasswordAuthentication)
|
||||||
.authorizationServerContext(AuthorizationServerContextHolder.getContext())
|
.authorizationServerContext(AuthorizationServerContextHolder.getContext())
|
||||||
.authorizationGrantType(WxMiniAppAuthenticationToken.WECHAT_MINI_APP)
|
.authorizationGrantType(WechatAuthenticationToken.WECHAT_MINI_APP)
|
||||||
.authorizationGrant(wxMiniAppAuthenticationToken);
|
.authorizationGrant(wechatAuthenticationToken);
|
||||||
|
|
||||||
// 生成访问令牌(Access Token)
|
// 生成访问令牌(Access Token)
|
||||||
OAuth2TokenContext tokenContext = tokenContextBuilder.tokenType(OAuth2TokenType.ACCESS_TOKEN).build();
|
OAuth2TokenContext tokenContext = tokenContextBuilder.tokenType(OAuth2TokenType.ACCESS_TOKEN).build();
|
||||||
@ -123,7 +123,7 @@ public class WxMiniAppAuthenticationProvider implements AuthenticationProvider {
|
|||||||
generatedAccessToken.getExpiresAt(), tokenContext.getAuthorizedScopes());
|
generatedAccessToken.getExpiresAt(), tokenContext.getAuthorizedScopes());
|
||||||
OAuth2Authorization.Builder authorizationBuilder = OAuth2Authorization.withRegisteredClient(registeredClient)
|
OAuth2Authorization.Builder authorizationBuilder = OAuth2Authorization.withRegisteredClient(registeredClient)
|
||||||
.principalName(userDetails.getUsername())
|
.principalName(userDetails.getUsername())
|
||||||
.authorizationGrantType(WxMiniAppAuthenticationToken.WECHAT_MINI_APP)
|
.authorizationGrantType(WechatAuthenticationToken.WECHAT_MINI_APP)
|
||||||
.attribute(Principal.class.getName(), usernamePasswordAuthentication);
|
.attribute(Principal.class.getName(), usernamePasswordAuthentication);
|
||||||
if (generatedAccessToken instanceof ClaimAccessor) {
|
if (generatedAccessToken instanceof ClaimAccessor) {
|
||||||
authorizationBuilder.token(accessToken, (metadata) ->
|
authorizationBuilder.token(accessToken, (metadata) ->
|
||||||
@ -157,7 +157,7 @@ public class WxMiniAppAuthenticationProvider implements AuthenticationProvider {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean supports(Class<?> authentication) {
|
public boolean supports(Class<?> authentication) {
|
||||||
return WxMiniAppAuthenticationToken.class.isAssignableFrom(authentication);
|
return WechatAuthenticationToken.class.isAssignableFrom(authentication);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package com.youlai.auth.oauth2.extension.miniapp;
|
package com.youlai.auth.oauth2.extension.wechat;
|
||||||
|
|
||||||
import jakarta.annotation.Nullable;
|
import jakarta.annotation.Nullable;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
@ -18,7 +18,7 @@ import java.util.Set;
|
|||||||
* @see OAuth2AuthorizationGrantAuthenticationToken
|
* @see OAuth2AuthorizationGrantAuthenticationToken
|
||||||
* @since 3.0.0
|
* @since 3.0.0
|
||||||
*/
|
*/
|
||||||
public class WxMiniAppAuthenticationToken extends OAuth2AuthorizationGrantAuthenticationToken {
|
public class WechatAuthenticationToken extends OAuth2AuthorizationGrantAuthenticationToken {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 令牌申请访问范围
|
* 令牌申请访问范围
|
||||||
@ -28,15 +28,15 @@ public class WxMiniAppAuthenticationToken extends OAuth2AuthorizationGrantAuthen
|
|||||||
/**
|
/**
|
||||||
* 授权类型:微信小程序
|
* 授权类型:微信小程序
|
||||||
*/
|
*/
|
||||||
public static final AuthorizationGrantType WECHAT_MINI_APP = new AuthorizationGrantType("wx_mini_app");
|
public static final AuthorizationGrantType WECHAT_MINI_APP = new AuthorizationGrantType("wechat");
|
||||||
|
|
||||||
|
|
||||||
protected WxMiniAppAuthenticationToken(
|
protected WechatAuthenticationToken(
|
||||||
Authentication clientPrincipal,
|
Authentication clientPrincipal,
|
||||||
Set<String> scopes,
|
Set<String> scopes,
|
||||||
@Nullable Map<String, Object> additionalParameters
|
@Nullable Map<String, Object> additionalParameters
|
||||||
) {
|
) {
|
||||||
super(WxMiniAppAuthenticationToken.WECHAT_MINI_APP, clientPrincipal, additionalParameters);
|
super(WechatAuthenticationToken.WECHAT_MINI_APP, clientPrincipal, additionalParameters);
|
||||||
this.scopes = Collections.unmodifiableSet(scopes != null ? new HashSet<>(scopes) : Collections.emptySet());
|
this.scopes = Collections.unmodifiableSet(scopes != null ? new HashSet<>(scopes) : Collections.emptySet());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user