Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
有来技术
youlai-mall
提交
9a991973
Y
youlai-mall
项目概览
有来技术
/
youlai-mall
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
Y
youlai-mall
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
9a991973
编写于
6月 09, 2023
作者:
郝
郝先瑞
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
refactor: 认证中心升级(临时提交勿clone)
上级
84aa6da7
变更
31
显示空白变更内容
内联
并排
Showing
31 changed file
with
566 addition
and
456 deletion
+566
-456
laboratory/pom.xml
laboratory/pom.xml
+2
-2
mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/model/dto/OrderDTO.java
...src/main/java/com/youlai/mall/oms/model/dto/OrderDTO.java
+2
-2
mall-ums/ums-api/src/main/java/com/youlai/mall/ums/api/MemberFeignClient.java
.../main/java/com/youlai/mall/ums/api/MemberFeignClient.java
+2
-2
mall-ums/ums-api/src/main/java/com/youlai/mall/ums/dto/MemberAuthDTO.java
.../src/main/java/com/youlai/mall/ums/dto/MemberAuthDTO.java
+4
-1
mall-ums/ums-api/src/main/java/com/youlai/mall/ums/dto/MemberRegisterDto.java
.../main/java/com/youlai/mall/ums/dto/MemberRegisterDto.java
+1
-1
mall-ums/ums-boot/src/main/java/com/youlai/mall/ums/controller/app/MemberController.java
.../com/youlai/mall/ums/controller/app/MemberController.java
+2
-2
mall-ums/ums-boot/src/main/java/com/youlai/mall/ums/convert/MemberConvert.java
.../main/java/com/youlai/mall/ums/convert/MemberConvert.java
+2
-2
mall-ums/ums-boot/src/main/java/com/youlai/mall/ums/service/IUmsMemberService.java
...n/java/com/youlai/mall/ums/service/IUmsMemberService.java
+2
-2
mall-ums/ums-boot/src/main/java/com/youlai/mall/ums/service/impl/UmsMemberServiceImpl.java
...om/youlai/mall/ums/service/impl/UmsMemberServiceImpl.java
+4
-4
pom.xml
pom.xml
+3
-13
youlai-auth/src/main/java/com/youlai/auth/authentication/mobile/SmsCodeAuthenticationProvider.java
.../authentication/mobile/SmsCodeAuthenticationProvider.java
+2
-2
youlai-auth/src/main/java/com/youlai/auth/authentication/refresh/PreAuthenticatedUserDetailsService.java
...ntication/refresh/PreAuthenticatedUserDetailsService.java
+5
-6
youlai-auth/src/main/java/com/youlai/auth/authentication/wechat/WeChatMiniProgramAuthenticationToken.java
...tication/wechat/WeChatMiniProgramAuthenticationToken.java
+61
-0
youlai-auth/src/main/java/com/youlai/auth/authentication/wechat/WechatAuthenticationConverter.java
.../authentication/wechat/WechatAuthenticationConverter.java
+0
-129
youlai-auth/src/main/java/com/youlai/auth/authentication/wechat/WechatAuthenticationProvider.java
...h/authentication/wechat/WechatAuthenticationProvider.java
+0
-167
youlai-auth/src/main/java/com/youlai/auth/authentication/wechat/WechatAuthenticationToken.java
...auth/authentication/wechat/WechatAuthenticationToken.java
+0
-51
youlai-auth/src/main/java/com/youlai/auth/authentication/wechat/WechatMiniProgramAuthenticationConverter.java
...tion/wechat/WechatMiniProgramAuthenticationConverter.java
+132
-0
youlai-auth/src/main/java/com/youlai/auth/authentication/wechat/WechatMiniProgramAuthenticationProvider.java
...ation/wechat/WechatMiniProgramAuthenticationProvider.java
+173
-0
youlai-auth/src/main/java/com/youlai/auth/authentication/wechat/WechatMiniProgramParameterNames.java
...uthentication/wechat/WechatMiniProgramParameterNames.java
+19
-0
youlai-auth/src/main/java/com/youlai/auth/authentication/wechat/WechatUserInfo.java
...com/youlai/auth/authentication/wechat/WechatUserInfo.java
+0
-27
youlai-auth/src/main/java/com/youlai/auth/config/WechatMiniappConfig.java
...main/java/com/youlai/auth/config/WechatMiniappConfig.java
+9
-5
youlai-auth/src/main/java/com/youlai/auth/userdetails/member/MmsUserDetails.java
...va/com/youlai/auth/userdetails/member/MmsUserDetails.java
+2
-2
youlai-auth/src/main/java/com/youlai/auth/userdetails/member/MmsUserDetailsService.java
...youlai/auth/userdetails/member/MmsUserDetailsService.java
+49
-18
youlai-auth/src/main/java/com/youlai/auth/userdetails/user/SysUserDetailsService.java
...m/youlai/auth/userdetails/user/SysUserDetailsService.java
+1
-1
youlai-auth/src/main/java/com/youlai/auth/util/OAuth2EndpointUtils.java
...c/main/java/com/youlai/auth/util/OAuth2EndpointUtils.java
+76
-0
youlai-common/common-core/src/main/java/com/youlai/common/result/ResultCode.java
...re/src/main/java/com/youlai/common/result/ResultCode.java
+1
-0
youlai-common/common-file/pom.xml
youlai-common/common-file/pom.xml
+2
-2
youlai-common/common-log/pom.xml
youlai-common/common-log/pom.xml
+2
-2
youlai-common/common-seata/pom.xml
youlai-common/common-seata/pom.xml
+4
-9
youlai-common/common-security/pom.xml
youlai-common/common-security/pom.xml
+2
-2
youlai-common/common-sms/pom.xml
youlai-common/common-sms/pom.xml
+2
-2
未找到文件。
laboratory/pom.xml
浏览文件 @
9a991973
...
...
@@ -13,8 +13,8 @@
<description>
有来实验室
</description>
<properties>
<maven.compiler.source>
8
</maven.compiler.source>
<maven.compiler.target>
8
</maven.compiler.target>
<maven.compiler.source>
17
</maven.compiler.source>
<maven.compiler.target>
17
</maven.compiler.target>
</properties>
<dependencies>
...
...
mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/model/dto/OrderDTO.java
浏览文件 @
9a991973
...
...
@@ -2,7 +2,7 @@ package com.youlai.mall.oms.model.dto;
import
com.youlai.mall.oms.model.entity.OmsOrder
;
import
com.youlai.mall.oms.model.entity.OmsOrderItem
;
import
com.youlai.mall.ums.dto.Member
DTO
;
import
com.youlai.mall.ums.dto.Member
RegisterDto
;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
...
...
@@ -22,6 +22,6 @@ public class OrderDTO {
private
List
<
OmsOrderItem
>
orderItems
;
private
Member
DTO
member
;
private
Member
RegisterDto
member
;
}
mall-ums/ums-api/src/main/java/com/youlai/mall/ums/api/MemberFeignClient.java
浏览文件 @
9a991973
...
...
@@ -4,7 +4,7 @@ import com.youlai.common.result.Result;
import
com.youlai.mall.pms.model.vo.ProductHistoryVO
;
import
com.youlai.mall.ums.dto.MemberAddressDTO
;
import
com.youlai.mall.ums.dto.MemberAuthDTO
;
import
com.youlai.mall.ums.dto.Member
DTO
;
import
com.youlai.mall.ums.dto.Member
RegisterDto
;
import
com.youlai.mall.ums.dto.MemberInfoDTO
;
import
org.springframework.cloud.openfeign.FeignClient
;
import
org.springframework.web.bind.annotation.*
;
...
...
@@ -27,7 +27,7 @@ public interface MemberFeignClient {
* @return
*/
@PostMapping
(
"/app-api/v1/members"
)
Result
<
Long
>
addMember
(
@RequestBody
MemberDTO
member
);
Result
<
Long
>
registerMember
(
@RequestBody
MemberRegisterDto
member
);
/**
* 获取会员的 openid
...
...
mall-ums/ums-api/src/main/java/com/youlai/mall/ums/dto/MemberAuthDTO.java
浏览文件 @
9a991973
package
com.youlai.mall.ums.dto
;
import
lombok.AllArgsConstructor
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
lombok.experimental.Accessors
;
/**
...
...
@@ -10,7 +12,8 @@ import lombok.experimental.Accessors;
* @since 2022/2/12
*/
@Data
@Accessors
(
chain
=
true
)
@AllArgsConstructor
@NoArgsConstructor
public
class
MemberAuthDTO
{
/**
...
...
mall-ums/ums-api/src/main/java/com/youlai/mall/ums/dto/Member
DTO
.java
→
mall-ums/ums-api/src/main/java/com/youlai/mall/ums/dto/Member
RegisterDto
.java
浏览文件 @
9a991973
...
...
@@ -11,7 +11,7 @@ import java.time.LocalDate;
* @since 2022/2/12
*/
@Data
public
class
Member
DTO
{
public
class
Member
RegisterDto
{
private
Integer
gender
;
...
...
mall-ums/ums-boot/src/main/java/com/youlai/mall/ums/controller/app/MemberController.java
浏览文件 @
9a991973
...
...
@@ -8,7 +8,7 @@ import com.youlai.common.security.util.SecurityUtils;
import
com.youlai.mall.pms.model.vo.ProductHistoryVO
;
import
com.youlai.mall.ums.dto.MemberAddressDTO
;
import
com.youlai.mall.ums.dto.MemberAuthDTO
;
import
com.youlai.mall.ums.dto.Member
DTO
;
import
com.youlai.mall.ums.dto.Member
RegisterDto
;
import
com.youlai.mall.ums.model.entity.UmsMember
;
import
com.youlai.mall.ums.model.vo.MemberVO
;
import
com.youlai.mall.ums.service.IUmsMemberService
;
...
...
@@ -40,7 +40,7 @@ public class MemberController {
@Operation
(
summary
=
"新增会员"
)
@PostMapping
public
Result
<
Long
>
addMember
(
@RequestBody
Member
DTO
member
)
{
public
Result
<
Long
>
addMember
(
@RequestBody
Member
RegisterDto
member
)
{
Long
memberId
=
memberService
.
addMember
(
member
);
return
Result
.
success
(
memberId
);
}
...
...
mall-ums/ums-boot/src/main/java/com/youlai/mall/ums/convert/MemberConvert.java
浏览文件 @
9a991973
package
com.youlai.mall.ums.convert
;
import
com.youlai.mall.ums.dto.MemberAuthDTO
;
import
com.youlai.mall.ums.dto.Member
DTO
;
import
com.youlai.mall.ums.dto.Member
RegisterDto
;
import
com.youlai.mall.ums.dto.MemberInfoDTO
;
import
com.youlai.mall.ums.model.entity.UmsMember
;
import
org.mapstruct.Mapper
;
...
...
@@ -30,5 +30,5 @@ public interface MemberConvert {
MemberInfoDTO
entity2MemberInfoDTO
(
UmsMember
entity
);
UmsMember
dto2Entity
(
Member
DTO
memb
erDTO
);
UmsMember
dto2Entity
(
Member
RegisterDto
memberRegist
erDTO
);
}
mall-ums/ums-boot/src/main/java/com/youlai/mall/ums/service/IUmsMemberService.java
浏览文件 @
9a991973
...
...
@@ -7,7 +7,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
import
com.youlai.mall.pms.model.vo.ProductHistoryVO
;
import
com.youlai.mall.ums.dto.MemberAddressDTO
;
import
com.youlai.mall.ums.dto.MemberAuthDTO
;
import
com.youlai.mall.ums.dto.Member
DTO
;
import
com.youlai.mall.ums.dto.Member
RegisterDto
;
import
com.youlai.mall.ums.dto.MemberInfoDTO
;
import
com.youlai.mall.ums.model.entity.UmsMember
;
import
com.youlai.mall.ums.model.vo.MemberVO
;
...
...
@@ -51,7 +51,7 @@ public interface IUmsMemberService extends IService<UmsMember> {
* @param member
* @return
*/
Long
addMember
(
Member
DTO
member
);
Long
addMember
(
Member
RegisterDto
member
);
/**
* 获取登录会员信息
...
...
mall-ums/ums-boot/src/main/java/com/youlai/mall/ums/service/impl/UmsMemberServiceImpl.java
浏览文件 @
9a991973
...
...
@@ -14,7 +14,7 @@ import com.youlai.mall.ums.convert.AddressConvert;
import
com.youlai.mall.ums.convert.MemberConvert
;
import
com.youlai.mall.ums.dto.MemberAddressDTO
;
import
com.youlai.mall.ums.dto.MemberAuthDTO
;
import
com.youlai.mall.ums.dto.Member
DTO
;
import
com.youlai.mall.ums.dto.Member
RegisterDto
;
import
com.youlai.mall.ums.dto.MemberInfoDTO
;
import
com.youlai.mall.ums.mapper.UmsMemberMapper
;
import
com.youlai.mall.ums.model.entity.UmsAddress
;
...
...
@@ -114,12 +114,12 @@ public class UmsMemberServiceImpl extends ServiceImpl<UmsMemberMapper, UmsMember
/**
* 新增会员
*
* @param memberDTO
* @param member
Register
DTO
* @return
*/
@Override
public
Long
addMember
(
Member
DTO
memb
erDTO
)
{
UmsMember
umsMember
=
memberConvert
.
dto2Entity
(
memberDTO
);
public
Long
addMember
(
Member
RegisterDto
memberRegist
erDTO
)
{
UmsMember
umsMember
=
memberConvert
.
dto2Entity
(
member
Register
DTO
);
boolean
result
=
this
.
save
(
umsMember
);
Assert
.
isTrue
(
result
,
"新增会员失败"
);
return
umsMember
.
getId
();
...
...
pom.xml
浏览文件 @
9a991973
...
...
@@ -41,15 +41,15 @@
<spring-boot.version>
3.1.0
</spring-boot.version>
<!-- spring cloud & alibaba -->
<spring-cloud.version>
2022.0.
2
</spring-cloud.version>
<spring-cloud.version>
2022.0.
3
</spring-cloud.version>
<spring-cloud-alibaba.version>
2022.0.0.0-RC2
</spring-cloud-alibaba.version>
<!-- -->
<!--
spring authorization server
-->
<authorization-server.version>
1.1.0
</authorization-server.version>
<nimbus-jose-jwt.version>
9.16.1
</nimbus-jose-jwt.version>
<!-- db && orm -->
<mysql.version>
8.0.28
</mysql.version>
<druid.version>
1.2.1
6
</druid.version>
<druid.version>
1.2.1
8
</druid.version>
<mybatis-plus.version>
3.5.3.1
</mybatis-plus.version>
<!-- api doc -->
...
...
@@ -66,7 +66,6 @@
<thumbnailator.version>
0.4.17
</thumbnailator.version>
<!-- distributed -->
<seata.version>
1.5.2
</seata.version>
<redisson.version>
3.21.0
</redisson.version>
<!-- 阿里云短信 -->
...
...
@@ -158,13 +157,6 @@
<version>
${weixin-java.version}
</version>
</dependency>
<dependency>
<groupId>
io.seata
</groupId>
<artifactId>
seata-spring-boot-starter
</artifactId>
<version>
${seata.version}
</version>
</dependency>
<!-- 分布式锁 -->
<dependency>
<groupId>
org.redisson
</groupId>
...
...
@@ -172,8 +164,6 @@
<version>
${redisson.version}
</version>
</dependency>
<dependency>
<groupId>
com.youlai
</groupId>
<artifactId>
common-core
</artifactId>
...
...
youlai-auth/src/main/java/com/youlai/auth/authentication/mobile/SmsCodeAuthenticationProvider.java
浏览文件 @
9a991973
package
com.youlai.auth.authentication.mobile
;
import
cn.hutool.core.util.StrUtil
;
import
com.youlai.auth.userdetails.member.M
emberUserDetailsServiceImpl
;
import
com.youlai.auth.userdetails.member.M
msUserDetailsService
;
import
com.youlai.common.constant.SecurityConstants
;
import
com.youlai.common.web.exception.BizException
;
import
com.youlai.mall.ums.api.MemberFeignClient
;
...
...
@@ -44,7 +44,7 @@ public class SmsCodeAuthenticationProvider implements AuthenticationProvider {
// 比对成功删除缓存的验证码
redisTemplate
.
delete
(
codeKey
);
}
UserDetails
userDetails
=
((
M
emberUserDetailsServiceImpl
)
userDetailsService
).
loadUserByMobile
(
mobile
);
UserDetails
userDetails
=
((
M
msUserDetailsService
)
userDetailsService
).
loadUserByMobile
(
mobile
);
SmsCodeAuthenticationToken
result
=
new
SmsCodeAuthenticationToken
(
userDetails
,
authentication
.
getCredentials
(),
new
HashSet
<>());
result
.
setDetails
(
authentication
.
getDetails
());
return
result
;
...
...
youlai-auth/src/main/java/com/youlai/auth/authentication/refresh/PreAuthenticatedUserDetailsService.java
浏览文件 @
9a991973
package
com.youlai.auth.authentication.refresh
;
import
com.youlai.auth.config.AuthorizationServerConfig
;
import
com.youlai.auth.userdetails.member.MemberUserDetailsServiceImpl
;
import
com.youlai.auth.userdetails.member.MmsUserDetailsService
;
import
com.youlai.auth.util.RequestUtils
;
import
com.youlai.common.constant.SecurityConstants
;
import
lombok.NoArgsConstructor
;
...
...
@@ -54,13 +53,13 @@ public class PreAuthenticatedUserDetailsService<T extends Authentication> implem
switch
(
clientId
)
{
case
SecurityConstants
.
APP_CLIENT_ID
->
{
// 移动端的用户体系是会员,认证方式是通过手机号 mobile 认证
M
emberUserDetailsServiceImpl
memberUserDetailsService
=
(
MemberUserDetailsServiceImpl
)
userDetailsService
;
return
m
ember
UserDetailsService
.
loadUserByUsername
(
authentication
.
getName
());
M
msUserDetailsService
mmsUserDetailsService
=
(
MmsUserDetailsService
)
userDetailsService
;
return
m
ms
UserDetailsService
.
loadUserByUsername
(
authentication
.
getName
());
}
case
SecurityConstants
.
WEAPP_CLIENT_ID
->
{
// 小程序的用户体系是会员,认证方式是通过微信三方标识 openid 认证
M
emberUserDetailsServiceImpl
memberUserDetailsService
=
(
MemberUserDetailsServiceImpl
)
userDetailsService
;
return
m
ember
UserDetailsService
.
loadUserByOpenId
(
authentication
.
getName
());
M
msUserDetailsService
mmsUserDetailsService
=
(
MmsUserDetailsService
)
userDetailsService
;
return
m
ms
UserDetailsService
.
loadUserByOpenId
(
authentication
.
getName
());
}
// 管理系统的用户体系是系统用户,认证方式通过用户名 username 认证
default
->
{
...
...
youlai-auth/src/main/java/com/youlai/auth/authentication/wechat/WeChatMiniProgramAuthenticationToken.java
0 → 100644
浏览文件 @
9a991973
package
com.youlai.auth.authentication.wechat
;
import
lombok.Getter
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.oauth2.core.AuthorizationGrantType
;
import
org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationCodeAuthenticationToken
;
import
org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationGrantAuthenticationToken
;
import
java.util.Map
;
/**
* 微信小程序
*
* @author haoxr
* @see OAuth2AuthorizationCodeAuthenticationToken
* @since 3.0.0
*/
public
class
WeChatMiniProgramAuthenticationToken
extends
OAuth2AuthorizationGrantAuthenticationToken
{
/**
* 授权类型:微信小程序
*/
public
static
final
AuthorizationGrantType
WECHAT_MINI_PROGRAM
=
new
AuthorizationGrantType
(
"wechat_mini_program"
);
@Getter
private
final
String
code
;
@Getter
private
final
String
encryptedData
;
@Getter
private
final
String
iv
;
/**
* @see org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames#SCOPE
*/
private
final
String
scope
;
/**
* Sub-class constructor.
*
* @param clientPrincipal the authenticated client principal
* @param additionalParameters the additional parameters
*/
protected
WeChatMiniProgramAuthenticationToken
(
Authentication
clientPrincipal
,
Map
<
String
,
Object
>
additionalParameters
,
String
code
,
String
encryptedData
,
String
iv
,
String
scope
)
{
super
(
WeChatMiniProgramAuthenticationToken
.
WECHAT_MINI_PROGRAM
,
clientPrincipal
,
additionalParameters
);
this
.
code
=
code
;
this
.
encryptedData
=
encryptedData
;
this
.
iv
=
iv
;
this
.
scope
=
scope
;
}
}
youlai-auth/src/main/java/com/youlai/auth/authentication/wechat/WechatAuthenticationConverter.java
已删除
100644 → 0
浏览文件 @
84aa6da7
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
);
}
}
youlai-auth/src/main/java/com/youlai/auth/authentication/wechat/WechatAuthenticationProvider.java
已删除
100644 → 0
浏览文件 @
84aa6da7
package
com.youlai.auth.authentication.wechat
;
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.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.security.Principal
;
import
java.util.*
;
import
java.util.stream.Collectors
;
/**
* 微信认证提供者
*
* @author haoxr
* @since 3.0.0
*/
@Slf4j
public
class
WechatAuthenticationProvider
implements
AuthenticationProvider
{
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 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
<?
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
{
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
<
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
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
);
}
}
youlai-auth/src/main/java/com/youlai/auth/authentication/wechat/WechatAuthenticationToken.java
已删除
100644 → 0
浏览文件 @
84aa6da7
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.*
;
/**
* 微信授权登录
*
* @author haoxr
* @since 3.0.0
*/
public
class
WechatAuthenticationToken
extends
OAuth2AuthorizationGrantAuthenticationToken
{
private
final
Set
<
String
>
scopes
;
/**
* {@link org.springframework.security.oauth2.server.authorization.authentication.OAuth2ClientCredentialsAuthenticationToken}
*
* @param clientPrincipal
* @param additionalParameters
*/
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
this
.
getAdditionalParameters
().
get
(
OAuth2ParameterNames
.
PASSWORD
);
}
}
youlai-auth/src/main/java/com/youlai/auth/authentication/wechat/WechatMiniProgramAuthenticationConverter.java
0 → 100644
浏览文件 @
9a991973
package
com.youlai.auth.authentication.wechat
;
import
cn.hutool.core.util.StrUtil
;
import
com.youlai.auth.authentication.password.ResourceOwnerPasswordAuthenticationToken
;
import
com.youlai.auth.util.OAuth2EndpointUtils
;
import
jakarta.servlet.http.HttpServletRequest
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.core.context.SecurityContextHolder
;
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
WechatMiniProgramAuthenticationConverter
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"
;
String
CODE
=
"code"
;
String
IV
=
"iv"
;
String
ENCRYPTED_DATA
=
"encryptedData"
;
@Override
public
Authentication
convert
(
HttpServletRequest
request
)
{
// grant_type (REQUIRED)
String
grantType
=
request
.
getParameter
(
OAuth2ParameterNames
.
GRANT_TYPE
);
if
(!
WeChatMiniProgramAuthenticationToken
.
WECHAT_MINI_PROGRAM
.
getValue
().
equals
(
grantType
))
{
return
null
;
}
MultiValueMap
<
String
,
String
>
parameters
=
OAuth2EndpointUtils
.
getParameters
(
request
);
// scope (OPTIONAL)
String
scope
=
parameters
.
getFirst
(
OAuth2ParameterNames
.
SCOPE
);
if
(
StringUtils
.
hasText
(
scope
)
&&
parameters
.
get
(
OAuth2ParameterNames
.
SCOPE
).
size
()
!=
1
)
{
OAuth2EndpointUtils
.
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
(
WechatMiniProgramParameterNames
.
CODE
);
if
(
StrUtil
.
isBlank
(
code
))
{
throwError
(
OAuth2ErrorCodes
.
INVALID_REQUEST
,
WechatMiniProgramParameterNames
.
CODE
,
ACCESS_TOKEN_REQUEST_ERROR_URI
);
}
// encryptedData (REQUIRED)
String
encryptedData
=
parameters
.
getFirst
(
WechatMiniProgramParameterNames
.
ENCRYPTED_DATA
);
if
(
StrUtil
.
isBlank
(
encryptedData
))
{
throwError
(
OAuth2ErrorCodes
.
INVALID_REQUEST
,
WechatMiniProgramParameterNames
.
ENCRYPTED_DATA
,
ACCESS_TOKEN_REQUEST_ERROR_URI
);
}
// iv (REQUIRED)
String
iv
=
parameters
.
getFirst
(
WechatMiniProgramParameterNames
.
IV
);
if
(
StrUtil
.
isBlank
(
iv
))
{
throwError
(
OAuth2ErrorCodes
.
INVALID_REQUEST
,
WechatMiniProgramParameterNames
.
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
)));
return
new
ResourceOwnerPasswordAuthenticationToken
(
clientPrincipal
,
requestedScopes
,
additionalParameters
);
}
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
);
}
}
youlai-auth/src/main/java/com/youlai/auth/authentication/wechat/WechatMiniProgramAuthenticationProvider.java
0 → 100644
浏览文件 @
9a991973
package
com.youlai.auth.authentication.wechat
;
import
cn.hutool.core.lang.Assert
;
import
com.youlai.auth.authentication.password.ResourceOwnerPasswordAuthenticationToken
;
import
com.youlai.auth.userdetails.member.MmsUserDetailsService
;
import
lombok.extern.slf4j.Slf4j
;
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.oauth2.core.*
;
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
java.security.Principal
;
import
java.util.Map
;
/**
* 微信认证提供者
*
* @author haoxr
* @since 3.0.0
*/
@Slf4j
public
class
WechatMiniProgramAuthenticationProvider
implements
AuthenticationProvider
{
private
static
final
String
ERROR_URI
=
"https://datatracker.ietf.org/doc/html/rfc6749#section-5.2"
;
private
final
OAuth2AuthorizationService
authorizationService
;
private
final
OAuth2TokenGenerator
<?
extends
OAuth2Token
>
tokenGenerator
;
private
final
MmsUserDetailsService
mmsUserDetailsService
;
/**
* 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
WechatMiniProgramAuthenticationProvider
(
OAuth2AuthorizationService
authorizationService
,
OAuth2TokenGenerator
<?
extends
OAuth2Token
>
tokenGenerator
,
MmsUserDetailsService
mmsUserDetailsService
)
{
Assert
.
notNull
(
authorizationService
,
"authorizationService cannot be null"
);
Assert
.
notNull
(
tokenGenerator
,
"tokenGenerator cannot be null"
);
this
.
authorizationService
=
authorizationService
;
this
.
tokenGenerator
=
tokenGenerator
;
this
.
mmsUserDetailsService
=
mmsUserDetailsService
;
}
@Override
public
Authentication
authenticate
(
Authentication
authentication
)
throws
AuthenticationException
{
WeChatMiniProgramAuthenticationToken
authenticationToken
=
(
WeChatMiniProgramAuthenticationToken
)
authentication
;
authenticationToken
.
getIv
()
// 验证客户端是否已认证
OAuth2ClientAuthenticationToken
clientPrincipal
=
getAuthenticatedClientElseThrowInvalidClient
(
authenticationToken
);
RegisteredClient
registeredClient
=
clientPrincipal
.
getRegisteredClient
();
// 验证客户端是否支持(grant_type=password)授权模式
if
(!
registeredClient
.
getAuthorizationGrantTypes
().
contains
(
AuthorizationGrantType
.
PASSWORD
))
{
throw
new
OAuth2AuthenticationException
(
OAuth2ErrorCodes
.
UNAUTHORIZED_CLIENT
);
}
// 密码验证
Map
<
String
,
Object
>
additionalParameters
=
authenticationToken
.
getAdditionalParameters
();
String
code
=
(
String
)
additionalParameters
.
get
(
"code"
);
String
encryptedData
=
(
String
)
additionalParameters
.
get
(
"encryptedData"
);
String
iv
=
(
String
)
additionalParameters
.
get
(
"iv"
);
UserDetails
userDetails
=
mmsUserDetailsService
.
loadUserByWechatCode
(
code
,
encryptedData
,
iv
);
UsernamePasswordAuthenticationToken
principal
=
UsernamePasswordAuthenticationToken
.
authenticated
(
userDetails
,
null
,
userDetails
.
getAuthorities
());
WeChatMiniProgramAuthenticationToken
weChatMiniProgramAuthenticationToken
=
new
WeChatMiniProgramAuthenticationToken
()
Authentication
usernamePasswordAuthentication
=
new
WeChatMiniProgramAuthenticationToken
();
// 生成 access_token
// @formatter:off
DefaultOAuth2TokenContext
.
Builder
tokenContextBuilder
=
DefaultOAuth2TokenContext
.
builder
()
.
registeredClient
(
registeredClient
)
.
principal
(
userDetails
.
getUsername
())
.
authorizationServerContext
(
AuthorizationServerContextHolder
.
getContext
())
.
authorizationGrantType
(
AuthorizationGrantType
.
PASSWORD
);
// @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
);
}
}
youlai-auth/src/main/java/com/youlai/auth/authentication/wechat/WechatMiniProgramParameterNames.java
0 → 100644
浏览文件 @
9a991973
package
com.youlai.auth.authentication.wechat
;
/**
* 微信小程序参数名称
*
* @author haoxr
* @since 3.0.0
*/
public
interface
WechatMiniProgramParameterNames
{
String
CODE
=
"code"
;
String
IV
=
"iv"
;
String
ENCRYPTED_DATA
=
"encryptedData"
;
}
youlai-auth/src/main/java/com/youlai/auth/authentication/wechat/WechatUserInfo.java
已删除
100644 → 0
浏览文件 @
84aa6da7
package
com.youlai.auth.authentication.wechat
;
import
lombok.Data
;
/**
* 微信用户信息
*
* @author <a href="mailto:xianrui0365@163.com">haoxr</a>
* @since 2021/10/4
*/
@Data
public
class
WechatUserInfo
{
private
String
avatarUrl
;
private
String
city
;
private
String
country
;
private
Integer
gender
;
private
String
language
;
private
String
nickName
;
private
String
province
;
}
youlai-auth/src/main/java/com/youlai/auth/config/Wechat
We
appConfig.java
→
youlai-auth/src/main/java/com/youlai/auth/config/Wechat
Mini
appConfig.java
浏览文件 @
9a991973
...
...
@@ -4,20 +4,24 @@ import cn.binarywang.wx.miniapp.api.WxMaService;
import
cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl
;
import
cn.binarywang.wx.miniapp.config.WxMaConfig
;
import
cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl
;
import
org.springframework.beans.factory.annotation.Value
;
import
lombok.Setter
;
import
org.springframework.boot.context.properties.ConfigurationProperties
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
/**
* 微信小程序配置
*
* @author haoxr
* @since 3.0.0
*/
@ConfigurationProperties
(
prefix
=
"miniapp.wechat"
)
@Configuration
public
class
Wechat
We
appConfig
{
public
class
Wechat
Mini
appConfig
{
@
Value
(
"${wechat.weapp.appid}"
)
@
Setter
private
String
appid
;
@Value
(
"${wechat.weapp.secret}"
)
@Setter
private
String
secret
;
@Bean
...
...
youlai-auth/src/main/java/com/youlai/auth/userdetails/member/M
ember
UserDetails.java
→
youlai-auth/src/main/java/com/youlai/auth/userdetails/member/M
ms
UserDetails.java
浏览文件 @
9a991973
...
...
@@ -17,7 +17,7 @@ import java.util.HashSet;
* @since 2021/9/27
*/
@Data
public
class
M
ember
UserDetails
implements
UserDetails
{
public
class
M
ms
UserDetails
implements
UserDetails
{
private
Long
memberId
;
private
String
username
;
...
...
@@ -34,7 +34,7 @@ public class MemberUserDetails implements UserDetails {
*
* @param member 小程序会员用户认证信息
*/
public
M
ember
UserDetails
(
MemberAuthDTO
member
)
{
public
M
ms
UserDetails
(
MemberAuthDTO
member
)
{
this
.
setMemberId
(
member
.
getMemberId
());
this
.
setUsername
(
member
.
getUsername
());
this
.
setEnabled
(
GlobalConstants
.
STATUS_YES
.
equals
(
member
.
getStatus
()));
...
...
youlai-auth/src/main/java/com/youlai/auth/userdetails/member/M
emberUserDetailsServiceImpl
.java
→
youlai-auth/src/main/java/com/youlai/auth/userdetails/member/M
msUserDetailsService
.java
浏览文件 @
9a991973
package
com.youlai.auth.userdetails.member
;
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
cn.hutool.core.lang.Assert
;
import
com.youlai.common.enums.StatusEnum
;
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.MemberRegisterDto
;
import
lombok.RequiredArgsConstructor
;
import
lombok.SneakyThrows
;
import
org.springframework.security.authentication.AccountExpiredException
;
import
org.springframework.security.authentication.DisabledException
;
import
org.springframework.security.authentication.LockedException
;
...
...
@@ -20,9 +28,10 @@ import org.springframework.stereotype.Service;
*/
@Service
(
"memberUserDetailsService"
)
@RequiredArgsConstructor
public
class
M
emberUserDetailsServiceImpl
implements
UserDetailsService
{
public
class
M
msUserDetailsService
implements
UserDetailsService
{
private
final
MemberFeignClient
memberFeignClient
;
private
final
WxMaService
wxMaService
;
@Override
public
UserDetails
loadUserByUsername
(
String
username
)
{
...
...
@@ -37,12 +46,12 @@ public class MemberUserDetailsServiceImpl implements UserDetailsService {
* @return
*/
public
UserDetails
loadUserByMobile
(
String
mobile
)
{
M
ember
UserDetails
userDetails
=
null
;
M
ms
UserDetails
userDetails
=
null
;
Result
<
MemberAuthDTO
>
result
=
memberFeignClient
.
loadUserByMobile
(
mobile
);
if
(
Result
.
isSuccess
(
result
))
{
MemberAuthDTO
member
=
result
.
getData
();
if
(
null
!=
member
)
{
userDetails
=
new
M
ember
UserDetails
(
member
);
userDetails
=
new
M
ms
UserDetails
(
member
);
}
}
if
(
userDetails
==
null
)
{
...
...
@@ -57,25 +66,45 @@ public class MemberUserDetailsServiceImpl implements UserDetailsService {
return
userDetails
;
}
/**
* openid 认证方式
*
* @param openId
* @return
*/
public
UserDetails
loadUserByOpenId
(
String
openId
)
{
MemberUserDetails
userDetails
=
null
;
Result
<
MemberAuthDTO
>
result
=
memberFeignClient
.
loadUserByOpenId
(
openId
);
if
(
Result
.
isSuccess
(
result
))
{
MemberAuthDTO
member
=
result
.
getData
();
if
(
null
!=
member
)
{
userDetails
=
new
MemberUserDetails
(
member
);
@SneakyThrows
public
UserDetails
loadUserByWechatCode
(
String
code
,
String
encryptedData
,
String
iv
)
{
// 根据 code 获取 openid
WxMaJscode2SessionResult
sessionInfo
=
wxMaService
.
getUserService
().
getSessionInfo
(
code
);
String
openid
=
sessionInfo
.
getOpenid
();
// 根据 openid 获取微信用户认证信息
Result
<
MemberAuthDTO
>
getMemberAuthInfoResult
=
memberFeignClient
.
loadUserByOpenId
(
openid
);
MemberAuthDTO
memberAuthInfo
=
null
;
// 会员不存在,注册成为新会员
if
(
ResultCode
.
USER_NOT_EXIST
.
getCode
().
equals
(
getMemberAuthInfoResult
.
getCode
()))
{
String
sessionKey
=
sessionInfo
.
getSessionKey
();
// 解密 encryptedData 获取用户信息
WxMaUserInfo
userInfo
=
wxMaService
.
getUserService
().
getUserInfo
(
sessionKey
,
encryptedData
,
iv
);
MemberRegisterDto
memberRegisterInfo
=
new
MemberRegisterDto
();
BeanUtil
.
copyProperties
(
userInfo
,
memberRegisterInfo
);
memberRegisterInfo
.
setOpenid
(
openid
);
// 注册会员
Result
<
Long
>
registerMemberResult
=
memberFeignClient
.
registerMember
(
memberRegisterInfo
);
// 注册成功将会员信息赋值给会员认证信息
Long
memberId
=
null
;
if
(
Result
.
isSuccess
(
registerMemberResult
)
&&
(
memberId
=
registerMemberResult
.
getData
())
!=
null
)
{
memberAuthInfo
=
new
MemberAuthDTO
(
memberId
,
openid
,
StatusEnum
.
ENABLE
.
getValue
());
}
}
else
{
Assert
.
isTrue
((
memberAuthInfo
=
getMemberAuthInfoResult
.
getData
())
!=
null
,
"获取会员认证信息失败"
);
}
if
(
userDetails
==
null
)
{
// 用户不存在
if
(
memberAuthInfo
==
null
)
{
throw
new
UsernameNotFoundException
(
ResultCode
.
USER_NOT_EXIST
.
getMsg
());
}
else
if
(!
userDetails
.
isEnabled
())
{
}
UserDetails
userDetails
=
new
MmsUserDetails
(
memberAuthInfo
);
if
(!
userDetails
.
isEnabled
())
{
throw
new
DisabledException
(
"该账户已被禁用!"
);
}
else
if
(!
userDetails
.
isAccountNonLocked
())
{
throw
new
LockedException
(
"该账号已被锁定!"
);
...
...
@@ -84,4 +113,6 @@ public class MemberUserDetailsServiceImpl implements UserDetailsService {
}
return
userDetails
;
}
}
youlai-auth/src/main/java/com/youlai/auth/userdetails/user/SysUserDetailsService
Impl
.java
→
youlai-auth/src/main/java/com/youlai/auth/userdetails/user/SysUserDetailsService.java
浏览文件 @
9a991973
...
...
@@ -20,7 +20,7 @@ import org.springframework.stereotype.Service;
@Service
(
"sysUserDetailsService"
)
@Slf4j
@RequiredArgsConstructor
public
class
SysUserDetailsService
Impl
implements
UserDetailsService
{
public
class
SysUserDetailsService
implements
UserDetailsService
{
private
final
UserFeignClient
userFeignClient
;
...
...
youlai-auth/src/main/java/com/youlai/auth/util/OAuth2EndpointUtils.java
0 → 100644
浏览文件 @
9a991973
package
com.youlai.auth.util
;
import
jakarta.servlet.http.HttpServletRequest
;
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.endpoint.OAuth2ParameterNames
;
import
org.springframework.security.oauth2.core.endpoint.PkceParameterNames
;
import
org.springframework.util.Assert
;
import
org.springframework.util.LinkedMultiValueMap
;
import
org.springframework.util.MultiValueMap
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.Map
;
/**
* @author haoxr
* @see org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2EndpointUtils
* @since 2023/6/8
*/
public
class
OAuth2EndpointUtils
{
static
final
String
ACCESS_TOKEN_REQUEST_ERROR_URI
=
"https://datatracker.ietf.org/doc/html/rfc6749#section-5.2"
;
public
OAuth2EndpointUtils
()
{
}
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
)
->
{
if
(
values
.
length
>
0
)
{
for
(
String
value
:
values
)
{
parameters
.
add
(
key
,
value
);
}
}
});
return
parameters
;
}
static
Map
<
String
,
Object
>
getParametersIfMatchesAuthorizationCodeGrantRequest
(
HttpServletRequest
request
,
String
...
exclusions
)
{
if
(!
matchesAuthorizationCodeGrantRequest
(
request
))
{
return
Collections
.
emptyMap
();
}
Map
<
String
,
Object
>
parameters
=
new
HashMap
<>(
getParameters
(
request
).
toSingleValueMap
());
for
(
String
exclusion
:
exclusions
)
{
parameters
.
remove
(
exclusion
);
}
return
parameters
;
}
static
boolean
matchesAuthorizationCodeGrantRequest
(
HttpServletRequest
request
)
{
return
AuthorizationGrantType
.
AUTHORIZATION_CODE
.
getValue
().
equals
(
request
.
getParameter
(
OAuth2ParameterNames
.
GRANT_TYPE
))
&&
request
.
getParameter
(
OAuth2ParameterNames
.
CODE
)
!=
null
;
}
static
boolean
matchesPkceTokenRequest
(
HttpServletRequest
request
)
{
return
matchesAuthorizationCodeGrantRequest
(
request
)
&&
request
.
getParameter
(
PkceParameterNames
.
CODE_VERIFIER
)
!=
null
;
}
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
);
}
static
String
normalizeUserCode
(
String
userCode
)
{
Assert
.
hasText
(
userCode
,
"userCode cannot be empty"
);
StringBuilder
sb
=
new
StringBuilder
(
userCode
.
toUpperCase
().
replaceAll
(
"[^A-Z\\d]+"
,
""
));
Assert
.
isTrue
(
sb
.
length
()
==
8
,
"userCode must be exactly 8 alpha/numeric characters"
);
sb
.
insert
(
4
,
'-'
);
return
sb
.
toString
();
}
}
youlai-common/common-core/src/main/java/com/youlai/common/result/ResultCode.java
浏览文件 @
9a991973
package
com.youlai.common.result
;
import
lombok.AllArgsConstructor
;
import
lombok.EqualsAndHashCode
;
import
lombok.NoArgsConstructor
;
import
java.io.Serializable
;
...
...
youlai-common/common-file/pom.xml
浏览文件 @
9a991973
...
...
@@ -12,8 +12,8 @@
<artifactId>
common-file
</artifactId>
<properties>
<maven.compiler.source>
8
</maven.compiler.source>
<maven.compiler.target>
8
</maven.compiler.target>
<maven.compiler.source>
17
</maven.compiler.source>
<maven.compiler.target>
17
</maven.compiler.target>
</properties>
<dependencies>
...
...
youlai-common/common-log/pom.xml
浏览文件 @
9a991973
...
...
@@ -12,8 +12,8 @@
<artifactId>
common-log
</artifactId>
<properties>
<maven.compiler.source>
8
</maven.compiler.source>
<maven.compiler.target>
8
</maven.compiler.target>
<maven.compiler.source>
17
</maven.compiler.source>
<maven.compiler.target>
17
</maven.compiler.target>
</properties>
</project>
\ No newline at end of file
youlai-common/common-seata/pom.xml
浏览文件 @
9a991973
...
...
@@ -12,8 +12,8 @@
<artifactId>
common-seata
</artifactId>
<properties>
<maven.compiler.source>
8
</maven.compiler.source>
<maven.compiler.target>
8
</maven.compiler.target>
<maven.compiler.source>
17
</maven.compiler.source>
<maven.compiler.target>
17
</maven.compiler.target>
<project.build.sourceEncoding>
UTF-8
</project.build.sourceEncoding>
</properties>
...
...
@@ -23,15 +23,10 @@
<artifactId>
spring-cloud-starter-alibaba-seata
</artifactId>
<exclusions>
<exclusion>
<groupId>
io.seat
a
</groupId>
<artifactId>
seata-spring-boot-starter
</artifactId>
<groupId>
com.alibab
a
</groupId>
<artifactId>
druid
</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>
io.seata
</groupId>
<artifactId>
seata-spring-boot-starter
</artifactId>
<version>
${seata.version}
</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
youlai-common/common-security/pom.xml
浏览文件 @
9a991973
...
...
@@ -12,8 +12,8 @@
<artifactId>
common-security
</artifactId>
<properties>
<maven.compiler.source>
8
</maven.compiler.source>
<maven.compiler.target>
8
</maven.compiler.target>
<maven.compiler.source>
17
</maven.compiler.source>
<maven.compiler.target>
17
</maven.compiler.target>
</properties>
<dependencies>
...
...
youlai-common/common-sms/pom.xml
浏览文件 @
9a991973
...
...
@@ -12,8 +12,8 @@
<artifactId>
common-sms
</artifactId>
<properties>
<maven.compiler.source>
8
</maven.compiler.source>
<maven.compiler.target>
8
</maven.compiler.target>
<maven.compiler.source>
17
</maven.compiler.source>
<maven.compiler.target>
17
</maven.compiler.target>
</properties>
<dependencies>
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录