Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
有来技术
youlai-mall
提交
a07a3c88
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,体验更适合开发者的 AI 搜索 >>
提交
a07a3c88
编写于
7月 04, 2023
作者:
郝
郝先瑞
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat: 自定义数据响应格式和添加刷新模式
上级
2807b604
变更
15
隐藏空白更改
内联
并排
Showing
15 changed file
with
268 addition
and
130 deletion
+268
-130
youlai-auth/src/main/java/com/youlai/auth/authentication/captcha/CaptchaAuthenticationProvider.java
...authentication/captcha/CaptchaAuthenticationProvider.java
+4
-57
youlai-auth/src/main/java/com/youlai/auth/config/AuthorizationServerConfig.java
...ava/com/youlai/auth/config/AuthorizationServerConfig.java
+33
-39
youlai-auth/src/main/java/com/youlai/auth/config/JwtCustomizerConfig.java
...main/java/com/youlai/auth/config/JwtCustomizerConfig.java
+79
-0
youlai-auth/src/main/java/com/youlai/auth/controller/AuthController.java
.../main/java/com/youlai/auth/controller/AuthController.java
+13
-0
youlai-auth/src/main/java/com/youlai/auth/handler/MyAuthenticationSuccessHandler.java
...m/youlai/auth/handler/MyAuthenticationSuccessHandler.java
+2
-2
youlai-auth/src/main/java/com/youlai/auth/userdetails/user/jackson/SysUseMixin.java
...com/youlai/auth/userdetails/user/jackson/SysUseMixin.java
+19
-0
youlai-auth/src/main/java/com/youlai/auth/userdetails/user/jackson/SysUserDeserializer.java
...ai/auth/userdetails/user/jackson/SysUserDeserializer.java
+83
-0
youlai-common/common-core/src/main/java/com/youlai/common/constant/SecurityConstants.java
...in/java/com/youlai/common/constant/SecurityConstants.java
+5
-12
youlai-common/common-security/src/main/java/com/youlai/common/security/config/ResourceServerConfig.java
...m/youlai/common/security/config/ResourceServerConfig.java
+5
-2
youlai-common/common-security/src/main/java/com/youlai/common/security/util/SecurityUtils.java
...n/java/com/youlai/common/security/util/SecurityUtils.java
+7
-10
youlai-system/system-boot/src/main/java/com/youlai/system/mapper/SysRoleMapper.java
...src/main/java/com/youlai/system/mapper/SysRoleMapper.java
+1
-1
youlai-system/system-boot/src/main/java/com/youlai/system/service/SysRoleService.java
...c/main/java/com/youlai/system/service/SysRoleService.java
+1
-1
youlai-system/system-boot/src/main/java/com/youlai/system/service/impl/SysRoleServiceImpl.java
...va/com/youlai/system/service/impl/SysRoleServiceImpl.java
+2
-2
youlai-system/system-boot/src/main/java/com/youlai/system/service/impl/SysUserServiceImpl.java
...va/com/youlai/system/service/impl/SysUserServiceImpl.java
+13
-3
youlai-system/system-boot/src/main/resources/mapper/SysRoleMapper.xml
...m/system-boot/src/main/resources/mapper/SysRoleMapper.xml
+1
-1
未找到文件。
youlai-auth/src/main/java/com/youlai/auth/authentication/captcha/CaptchaAuthenticationProvider.java
浏览文件 @
a07a3c88
...
...
@@ -13,10 +13,6 @@ 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.OidcIdToken
;
import
org.springframework.security.oauth2.core.oidc.OidcScopes
;
import
org.springframework.security.oauth2.core.oidc.endpoint.OidcParameterNames
;
import
org.springframework.security.oauth2.jwt.Jwt
;
import
org.springframework.security.oauth2.server.authorization.OAuth2Authorization
;
import
org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService
;
import
org.springframework.security.oauth2.server.authorization.OAuth2TokenType
;
...
...
@@ -27,11 +23,10 @@ import org.springframework.security.oauth2.server.authorization.context.Authoriz
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
;
import
java.util.
Collections
;
import
java.util.
Map
;
/**
* 验证码模式身份验证提供者
...
...
@@ -45,10 +40,7 @@ import java.util.stream.Collectors;
@Slf4j
public
class
CaptchaAuthenticationProvider
implements
AuthenticationProvider
{
private
static
final
String
ERROR_URI
=
"https://datatracker.ietf.org/doc/html/rfc6749#section-5.2"
;
private
static
final
OAuth2TokenType
ID_TOKEN_TOKEN_TYPE
=
new
OAuth2TokenType
(
OidcParameterNames
.
ID_TOKEN
);
private
final
AuthenticationManager
authenticationManager
;
private
final
OAuth2AuthorizationService
authorizationService
;
private
final
OAuth2TokenGenerator
<?
extends
OAuth2Token
>
tokenGenerator
;
...
...
@@ -93,7 +85,7 @@ public class CaptchaAuthenticationProvider implements AuthenticationProvider {
String
verifyCode
=
(
String
)
additionalParameters
.
get
(
CaptchaParameterNames
.
VERIFY_CODE
);
String
verifyCodeKey
=
(
String
)
additionalParameters
.
get
(
CaptchaParameterNames
.
VERIFY_CODE_KEY
);
String
cacheCode
=
redisTemplate
.
opsForValue
().
get
(
SecurityConstants
.
VERIFY_CODE_KEY_PREFIX
+
verifyCodeKey
);
String
cacheCode
=
redisTemplate
.
opsForValue
().
get
(
SecurityConstants
.
VERIFY_CODE_KEY_PREFIX
+
verifyCodeKey
);
if
(!
StrUtil
.
equals
(
verifyCode
,
cacheCode
))
{
throw
new
OAuth2AuthenticationException
(
"验证码错误"
);
}
...
...
@@ -105,25 +97,11 @@ public class CaptchaAuthenticationProvider implements AuthenticationProvider {
// 用户名密码身份验证,成功后返回带有权限的认证信息
Authentication
usernamePasswordAuthentication
=
authenticationManager
.
authenticate
(
usernamePasswordAuthenticationToken
);
// 验证申请访问范围(Scope)
Set
<
String
>
authorizedScopes
=
registeredClient
.
getScopes
();
Set
<
String
>
requestedScopes
=
captchaAuthenticationToken
.
getScopes
();
if
(!
CollectionUtils
.
isEmpty
(
requestedScopes
))
{
Set
<
String
>
unauthorizedScopes
=
requestedScopes
.
stream
()
.
filter
(
requestedScope
->
!
registeredClient
.
getScopes
().
contains
(
requestedScope
))
.
collect
(
Collectors
.
toSet
());
if
(!
CollectionUtils
.
isEmpty
(
unauthorizedScopes
))
{
throw
new
OAuth2AuthenticationException
(
OAuth2ErrorCodes
.
INVALID_SCOPE
);
}
authorizedScopes
=
new
LinkedHashSet
<>(
requestedScopes
);
}
// 访问令牌(Access Token) 构造器
DefaultOAuth2TokenContext
.
Builder
tokenContextBuilder
=
DefaultOAuth2TokenContext
.
builder
()
.
registeredClient
(
registeredClient
)
.
principal
(
usernamePasswordAuthentication
)
// 身份验证成功的认证信息(用户名、权限等信息)
.
authorizationServerContext
(
AuthorizationServerContextHolder
.
getContext
())
.
authorizedScopes
(
authorizedScopes
)
.
authorizationGrantType
(
CaptchaAuthenticationToken
.
CAPTCHA
)
// 授权方式
.
authorizationGrant
(
captchaAuthenticationToken
)
// 授权具体对象
;
...
...
@@ -144,7 +122,6 @@ public class CaptchaAuthenticationProvider implements AuthenticationProvider {
OAuth2Authorization
.
Builder
authorizationBuilder
=
OAuth2Authorization
.
withRegisteredClient
(
registeredClient
)
.
principalName
(
usernamePasswordAuthentication
.
getName
())
.
authorizationGrantType
(
CaptchaAuthenticationToken
.
CAPTCHA
)
.
authorizedScopes
(
authorizedScopes
)
.
attribute
(
Principal
.
class
.
getName
(),
usernamePasswordAuthentication
);
if
(
generatedAccessToken
instanceof
ClaimAccessor
)
{
authorizationBuilder
.
token
(
accessToken
,
(
metadata
)
->
...
...
@@ -171,39 +148,9 @@ public class CaptchaAuthenticationProvider implements AuthenticationProvider {
authorizationBuilder
.
refreshToken
(
refreshToken
);
}
// 生成 ID token
OidcIdToken
idToken
;
if
(
requestedScopes
.
contains
(
OidcScopes
.
OPENID
))
{
// @formatter:off
tokenContext
=
tokenContextBuilder
.
tokenType
(
ID_TOKEN_TOKEN_TYPE
)
.
authorization
(
authorizationBuilder
.
build
())
// ID token customizer may need access to the access token and/or refresh token
.
build
();
// @formatter:on
OAuth2Token
generatedIdToken
=
this
.
tokenGenerator
.
generate
(
tokenContext
);
if
(!(
generatedIdToken
instanceof
Jwt
))
{
OAuth2Error
error
=
new
OAuth2Error
(
OAuth2ErrorCodes
.
SERVER_ERROR
,
"The token generator failed to generate the ID token."
,
ERROR_URI
);
throw
new
OAuth2AuthenticationException
(
error
);
}
idToken
=
new
OidcIdToken
(
generatedIdToken
.
getTokenValue
(),
generatedIdToken
.
getIssuedAt
(),
generatedIdToken
.
getExpiresAt
(),
((
Jwt
)
generatedIdToken
).
getClaims
());
authorizationBuilder
.
token
(
idToken
,
(
metadata
)
->
metadata
.
put
(
OAuth2Authorization
.
Token
.
CLAIMS_METADATA_NAME
,
idToken
.
getClaims
()));
}
else
{
idToken
=
null
;
}
OAuth2Authorization
authorization
=
authorizationBuilder
.
build
();
this
.
authorizationService
.
save
(
authorization
);
additionalParameters
=
Collections
.
emptyMap
();
if
(
idToken
!=
null
)
{
additionalParameters
=
new
HashMap
<>();
additionalParameters
.
put
(
OidcParameterNames
.
ID_TOKEN
,
idToken
.
getTokenValue
());
}
additionalParameters
=
Collections
.
EMPTY_MAP
;
return
new
OAuth2AccessTokenAuthenticationToken
(
registeredClient
,
clientPrincipal
,
accessToken
,
refreshToken
,
additionalParameters
);
}
...
...
youlai-auth/src/main/java/com/youlai/auth/config/AuthorizationServerConfig.java
浏览文件 @
a07a3c88
...
...
@@ -2,13 +2,13 @@
package
com.youlai.auth.config
;
import
cn.binarywang.wx.miniapp.api.WxMaService
;
import
cn.hutool.json.JSONUtil
;
import
com.fasterxml.jackson.databind.Module
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.nimbusds.jose.jwk.JWKSet
;
import
com.nimbusds.jose.jwk.RSAKey
;
import
com.nimbusds.jose.jwk.source.ImmutableJWKSet
;
import
com.nimbusds.jose.jwk.source.JWKSource
;
import
com.nimbusds.jose.proc.SecurityContext
;
import
com.nimbusds.jose.shaded.json.JSONObject
;
import
com.youlai.auth.authentication.captcha.CaptchaAuthenticationConverter
;
import
com.youlai.auth.authentication.captcha.CaptchaAuthenticationProvider
;
import
com.youlai.auth.authentication.captcha.CaptchaAuthenticationToken
;
...
...
@@ -21,57 +21,52 @@ import com.youlai.auth.authentication.wxminiapp.WxMiniAppAuthenticationConverter
import
com.youlai.auth.authentication.wxminiapp.WxMiniAppAuthenticationProvider
;
import
com.youlai.auth.authentication.wxminiapp.WxMiniAppAuthenticationToken
;
import
com.youlai.auth.handler.MyAuthenticationSuccessHandler
;
import
com.youlai.auth.userdetails.member.MemberDetails
;
import
com.youlai.auth.userdetails.member.MemberDetailsService
;
import
com.youlai.auth.userdetails.user.SysUserDetails
;
import
com.youlai.common.result.Result
;
import
jakarta.servlet.http.HttpServletResponse
;
import
com.youlai.auth.userdetails.user.jackson.SysUseMixin
;
import
lombok.RequiredArgsConstructor
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.core.Ordered
;
import
org.springframework.core.annotation.Order
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.data.redis.core.StringRedisTemplate
;
import
org.springframework.jdbc.core.JdbcTemplate
;
import
org.springframework.jdbc.support.lob.DefaultLobHandler
;
import
org.springframework.security.authentication.AuthenticationManager
;
import
org.springframework.security.authentication.UsernamePasswordAuthenticationToken
;
import
org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration
;
import
org.springframework.security.config.annotation.web.builders.HttpSecurity
;
import
org.springframework.security.crypto.factory.PasswordEncoderFactories
;
import
org.springframework.security.crypto.password.PasswordEncoder
;
import
org.springframework.security.jackson2.SecurityJackson2Modules
;
import
org.springframework.security.oauth2.core.AuthorizationGrantType
;
import
org.springframework.security.oauth2.core.ClientAuthenticationMethod
;
import
org.springframework.security.oauth2.core.oidc.OidcScopes
;
import
org.springframework.security.oauth2.core.oidc.endpoint.OidcParameterNames
;
import
org.springframework.security.oauth2.jwt.JwtClaimsSet
;
import
org.springframework.security.oauth2.jwt.JwtDecoder
;
import
org.springframework.security.oauth2.jwt.NimbusJwtEncoder
;
import
org.springframework.security.oauth2.server.authorization.*
;
import
org.springframework.security.oauth2.server.authorization.authentication.OAuth2AccessTokenAuthenticationToken
;
import
org.springframework.security.oauth2.server.authorization.JdbcOAuth2AuthorizationConsentService
;
import
org.springframework.security.oauth2.server.authorization.JdbcOAuth2AuthorizationService
;
import
org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsentService
;
import
org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService
;
import
org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository
;
import
org.springframework.security.oauth2.server.authorization.client.RegisteredClient
;
import
org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository
;
import
org.springframework.security.oauth2.server.authorization.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration
;
import
org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2AuthorizationServerConfigurer
;
import
org.springframework.security.oauth2.server.authorization.jackson2.OAuth2AuthorizationServerJackson2Module
;
import
org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings
;
import
org.springframework.security.oauth2.server.authorization.settings.ClientSettings
;
import
org.springframework.security.oauth2.server.authorization.settings.TokenSettings
;
import
org.springframework.security.oauth2.server.authorization.token.*
;
import
org.springframework.security.web.SecurityFilterChain
;
import
org.springframework.security.web.util.matcher.RequestMatcher
;
import
org.springframework.web.util.ContentCachingResponseWrapper
;
import
org.springframework.web.util.WebUtils
;
import
java.io.IOException
;
import
java.io.PrintWriter
;
import
java.io.StringWriter
;
import
java.security.KeyPair
;
import
java.security.KeyPairGenerator
;
import
java.security.interfaces.RSAPrivateKey
;
import
java.security.interfaces.RSAPublicKey
;
import
java.time.Duration
;
import
java.util.List
;
import
java.util.Optional
;
import
java.util.UUID
;
/**
...
...
@@ -88,7 +83,7 @@ public class AuthorizationServerConfig {
private
final
WxMaService
wxMaService
;
private
final
StringRedisTemplate
redisTemplate
;
private
final
MemberDetailsService
memberDetailsService
;
private
final
OAuth2TokenCustomizer
<
JwtEncodingContext
>
jwtCustomizer
;
/**
* 授权配置
...
...
@@ -203,7 +198,22 @@ public class AuthorizationServerConfig {
@Bean
public
OAuth2AuthorizationService
authorizationService
(
JdbcTemplate
jdbcTemplate
,
RegisteredClientRepository
registeredClientRepository
)
{
return
new
JdbcOAuth2AuthorizationService
(
jdbcTemplate
,
registeredClientRepository
);
JdbcOAuth2AuthorizationService
service
=
new
JdbcOAuth2AuthorizationService
(
jdbcTemplate
,
registeredClientRepository
);
JdbcOAuth2AuthorizationService
.
OAuth2AuthorizationRowMapper
rowMapper
=
new
JdbcOAuth2AuthorizationService
.
OAuth2AuthorizationRowMapper
(
registeredClientRepository
);
rowMapper
.
setLobHandler
(
new
DefaultLobHandler
());
ObjectMapper
objectMapper
=
new
ObjectMapper
();
ClassLoader
classLoader
=
JdbcOAuth2AuthorizationService
.
class
.
getClassLoader
();
List
<
Module
>
securityModules
=
SecurityJackson2Modules
.
getModules
(
classLoader
);
objectMapper
.
registerModules
(
securityModules
);
objectMapper
.
registerModule
(
new
OAuth2AuthorizationServerJackson2Module
());
// You will need to write the Mixin for your class so Jackson can marshall it.
objectMapper
.
addMixIn
(
SysUserDetails
.
class
,
SysUseMixin
.
class
);
objectMapper
.
addMixIn
(
Long
.
class
,
Object
.
class
);
rowMapper
.
setObjectMapper
(
objectMapper
);
service
.
setAuthorizationRowMapper
(
rowMapper
);
return
service
;
}
@Bean
...
...
@@ -217,7 +227,7 @@ public class AuthorizationServerConfig {
@Bean
OAuth2TokenGenerator
<?>
tokenGenerator
(
JWKSource
<
SecurityContext
>
jwkSource
)
{
JwtGenerator
jwtGenerator
=
new
JwtGenerator
(
new
NimbusJwtEncoder
(
jwkSource
));
jwtGenerator
.
setJwtCustomizer
(
jwtCustomizer
()
);
jwtGenerator
.
setJwtCustomizer
(
jwtCustomizer
);
OAuth2AccessTokenGenerator
accessTokenGenerator
=
new
OAuth2AccessTokenGenerator
();
OAuth2RefreshTokenGenerator
refreshTokenGenerator
=
new
OAuth2RefreshTokenGenerator
();
...
...
@@ -226,25 +236,7 @@ public class AuthorizationServerConfig {
}
@Bean
public
OAuth2TokenCustomizer
<
JwtEncodingContext
>
jwtCustomizer
()
{
return
context
->
{
if
(
OAuth2TokenType
.
ACCESS_TOKEN
.
equals
(
context
.
getTokenType
())
&&
context
.
getPrincipal
()
instanceof
UsernamePasswordAuthenticationToken
)
{
// Customize headers/claims for access_token
Optional
.
ofNullable
(
context
.
getPrincipal
().
getPrincipal
()).
ifPresent
(
principal
->
{
JwtClaimsSet
.
Builder
claims
=
context
.
getClaims
();
if
(
principal
instanceof
SysUserDetails
userDetails
)
{
claims
.
claim
(
"user_id"
,
String
.
valueOf
(
userDetails
.
getUserId
()));
}
else
if
(
principal
instanceof
MemberDetails
userDetails
)
{
claims
.
claim
(
"member_id"
,
String
.
valueOf
(
userDetails
.
getId
()));
}
});
}
else
if
(
context
.
getTokenType
().
getValue
().
equals
(
OidcParameterNames
.
ID_TOKEN
))
{
// Customize headers/claims for id_token
}
};
}
@Bean
...
...
@@ -284,6 +276,7 @@ public class AuthorizationServerConfig {
.
postLogoutRedirectUri
(
"http://127.0.0.1:8080/logged-out"
)
.
scope
(
OidcScopes
.
OPENID
)
.
scope
(
OidcScopes
.
PROFILE
)
.
tokenSettings
(
TokenSettings
.
builder
().
accessTokenTimeToLive
(
Duration
.
ofDays
(
1
)).
build
())
.
clientSettings
(
ClientSettings
.
builder
().
requireAuthorizationConsent
(
true
).
build
())
.
build
();
registeredClientRepository
.
save
(
mallAppClient
);
...
...
@@ -320,6 +313,7 @@ public class AuthorizationServerConfig {
.
postLogoutRedirectUri
(
"http://127.0.0.1:8080/logged-out"
)
.
scope
(
OidcScopes
.
OPENID
)
.
scope
(
OidcScopes
.
PROFILE
)
.
tokenSettings
(
TokenSettings
.
builder
().
accessTokenTimeToLive
(
Duration
.
ofDays
(
1
)).
build
())
.
clientSettings
(
ClientSettings
.
builder
().
requireAuthorizationConsent
(
true
).
build
())
.
build
();
registeredClientRepository
.
save
(
mallAppClient
);
...
...
youlai-auth/src/main/java/com/youlai/auth/config/JwtCustomizerConfig.java
0 → 100644
浏览文件 @
a07a3c88
package
com.youlai.auth.config
;
import
com.youlai.auth.userdetails.member.MemberDetails
;
import
com.youlai.auth.userdetails.user.SysUserDetails
;
import
com.youlai.common.constant.SecurityConstants
;
import
lombok.RequiredArgsConstructor
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.security.authentication.UsernamePasswordAuthenticationToken
;
import
org.springframework.security.core.GrantedAuthority
;
import
org.springframework.security.core.authority.AuthorityUtils
;
import
org.springframework.security.core.userdetails.User
;
import
org.springframework.security.oauth2.core.oidc.endpoint.OidcParameterNames
;
import
org.springframework.security.oauth2.jwt.JwtClaimsSet
;
import
org.springframework.security.oauth2.server.authorization.OAuth2TokenType
;
import
org.springframework.security.oauth2.server.authorization.token.JwtEncodingContext
;
import
org.springframework.security.oauth2.server.authorization.token.OAuth2TokenCustomizer
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.Optional
;
import
java.util.Set
;
import
java.util.stream.Collectors
;
/**
* 自定义 JWT 的 Claims(声明)
*
* @author haoxr
* @since 2023/7/4
*/
@Configuration
@RequiredArgsConstructor
public
class
JwtCustomizerConfig
{
private
final
RedisTemplate
redisTemplate
;
@Bean
public
OAuth2TokenCustomizer
<
JwtEncodingContext
>
jwtCustomizer
()
{
return
context
->
{
if
(
OAuth2TokenType
.
ACCESS_TOKEN
.
equals
(
context
.
getTokenType
())
&&
context
.
getPrincipal
()
instanceof
UsernamePasswordAuthenticationToken
)
{
// Customize headers/claims for access_token
Optional
.
ofNullable
(
context
.
getPrincipal
().
getPrincipal
()).
ifPresent
(
principal
->
{
JwtClaimsSet
.
Builder
claims
=
context
.
getClaims
();
if
(
principal
instanceof
SysUserDetails
userDetails
)
{
Long
userId
=
userDetails
.
getUserId
();
claims
.
claim
(
"user_id"
,
userId
);
// 这里存入角色至JWT,解析JWT的角色用于鉴权的位置: ResourceServerConfig#jwtAuthenticationConverter
var
authorities
=
AuthorityUtils
.
authorityListToSet
(
context
.
getPrincipal
().
getAuthorities
())
.
stream
()
.
collect
(
Collectors
.
collectingAndThen
(
Collectors
.
toSet
(),
Collections:
:
unmodifiableSet
));
claims
.
claim
(
SecurityConstants
.
AUTHORITIES_CLAIM_NAME_KEY
,
authorities
);
// 权限数据比较多,缓存至redis
Set
<
String
>
perms
=
userDetails
.
getPerms
();
redisTemplate
.
opsForValue
().
set
(
SecurityConstants
.
USER_PERMS_CACHE_PREFIX
+
userId
,
perms
);
}
else
if
(
principal
instanceof
MemberDetails
userDetails
)
{
claims
.
claim
(
"member_id"
,
String
.
valueOf
(
userDetails
.
getId
()));
}
else
{
User
user
=
(
User
)
principal
;
// 这里存入角色至JWT,解析JWT的角色用于鉴权的位置: ResourceServerConfig#jwtAuthenticationConverter
var
authorities
=
AuthorityUtils
.
authorityListToSet
(
context
.
getPrincipal
().
getAuthorities
())
.
stream
()
.
collect
(
Collectors
.
collectingAndThen
(
Collectors
.
toSet
(),
Collections:
:
unmodifiableSet
));
claims
.
claim
(
SecurityConstants
.
AUTHORITIES_CLAIM_NAME_KEY
,
authorities
);
}
});
}
else
if
(
context
.
getTokenType
().
getValue
().
equals
(
OidcParameterNames
.
ID_TOKEN
))
{
// Customize headers/claims for id_token
}
};
}
}
youlai-auth/src/main/java/com/youlai/auth/controller/AuthController.java
0 → 100644
浏览文件 @
a07a3c88
package
com.youlai.auth.controller
;
import
org.springframework.web.bind.annotation.RestController
;
/**
* @author haoxr
* @since 2023/6/29
*/
@RestController
public
class
AuthController
{
}
youlai-auth/src/main/java/com/youlai/auth/handler/MyAuthenticationSuccessHandler.java
浏览文件 @
a07a3c88
...
...
@@ -52,8 +52,7 @@ public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHand
OAuth2AccessTokenResponse
.
Builder
builder
=
OAuth2AccessTokenResponse
.
withToken
(
accessToken
.
getTokenValue
())
.
tokenType
(
accessToken
.
getTokenType
())
.
scopes
(
accessToken
.
getScopes
());
.
tokenType
(
accessToken
.
getTokenType
());
if
(
accessToken
.
getIssuedAt
()
!=
null
&&
accessToken
.
getExpiresAt
()
!=
null
)
{
builder
.
expiresIn
(
ChronoUnit
.
SECONDS
.
between
(
accessToken
.
getIssuedAt
(),
accessToken
.
getExpiresAt
()));
}
...
...
@@ -68,6 +67,7 @@ public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHand
Map
<
String
,
Object
>
tokenResponseParameters
=
this
.
accessTokenResponseParametersConverter
.
convert
(
accessTokenResponse
);
response
.
setCharacterEncoding
(
"UTF-8"
);
response
.
getWriter
().
write
(
JSONUtil
.
toJsonStr
(
Result
.
success
(
tokenResponseParameters
)));
...
...
youlai-auth/src/main/java/com/youlai/auth/userdetails/user/jackson/SysUseMixin.java
0 → 100644
浏览文件 @
a07a3c88
package
com.youlai.auth.userdetails.user.jackson
;
import
com.fasterxml.jackson.annotation.JsonAutoDetect
;
import
com.fasterxml.jackson.annotation.JsonIgnoreProperties
;
import
com.fasterxml.jackson.annotation.JsonTypeInfo
;
import
com.fasterxml.jackson.databind.annotation.JsonDeserialize
;
/**
* @see org.springframework.security.jackson2.UserMixin
*
* @author haoxr
* @since 2023/7/4
*/
@JsonTypeInfo
(
use
=
JsonTypeInfo
.
Id
.
CLASS
,
include
=
JsonTypeInfo
.
As
.
PROPERTY
)
@JsonDeserialize
(
using
=
SysUserDeserializer
.
class
)
@JsonAutoDetect
(
fieldVisibility
=
JsonAutoDetect
.
Visibility
.
ANY
,
getterVisibility
=
JsonAutoDetect
.
Visibility
.
NONE
,
isGetterVisibility
=
JsonAutoDetect
.
Visibility
.
NONE
)
@JsonIgnoreProperties
(
ignoreUnknown
=
true
)
public
class
SysUseMixin
{
}
youlai-auth/src/main/java/com/youlai/auth/userdetails/user/jackson/SysUserDeserializer.java
0 → 100644
浏览文件 @
a07a3c88
/*
* Copyright 2015-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com.youlai.auth.userdetails.user.jackson
;
import
com.fasterxml.jackson.core.JsonParser
;
import
com.fasterxml.jackson.core.JsonProcessingException
;
import
com.fasterxml.jackson.core.type.TypeReference
;
import
com.fasterxml.jackson.databind.DeserializationContext
;
import
com.fasterxml.jackson.databind.JsonDeserializer
;
import
com.fasterxml.jackson.databind.JsonNode
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.fasterxml.jackson.databind.node.MissingNode
;
import
org.springframework.security.core.GrantedAuthority
;
import
org.springframework.security.core.authority.SimpleGrantedAuthority
;
import
org.springframework.security.core.userdetails.User
;
import
java.io.IOException
;
import
java.util.Set
;
/**
* Custom Deserializer for {@link User} class. This is already registered with
* {@link UserMixin}. You can also use it directly with your mixin class.
*
* @author Jitendra Singh
* @since 4.2
* @see UserMixin
*/
class
SysUserDeserializer
extends
JsonDeserializer
<
User
>
{
private
static
final
TypeReference
<
Set
<
SimpleGrantedAuthority
>>
SIMPLE_GRANTED_AUTHORITY_SET
=
new
TypeReference
<
Set
<
SimpleGrantedAuthority
>>()
{
};
/**
* This method will create {@link User} object. It will ensure successful object
* creation even if password key is null in serialized json, because credentials may
* be removed from the {@link User} by invoking {@link User#eraseCredentials()}. In
* that case there won't be any password key in serialized json.
* @param jp the JsonParser
* @param ctxt the DeserializationContext
* @return the user
* @throws IOException if a exception during IO occurs
* @throws JsonProcessingException if an error during JSON processing occurs
*/
@Override
public
User
deserialize
(
JsonParser
jp
,
DeserializationContext
ctxt
)
throws
IOException
,
JsonProcessingException
{
ObjectMapper
mapper
=
(
ObjectMapper
)
jp
.
getCodec
();
JsonNode
jsonNode
=
mapper
.
readTree
(
jp
);
Set
<?
extends
GrantedAuthority
>
authorities
=
mapper
.
convertValue
(
jsonNode
.
get
(
"authorities"
),
SIMPLE_GRANTED_AUTHORITY_SET
);
JsonNode
passwordNode
=
readJsonNode
(
jsonNode
,
"password"
);
String
username
=
readJsonNode
(
jsonNode
,
"username"
).
asText
();
String
password
=
passwordNode
.
asText
(
""
);
boolean
enabled
=
readJsonNode
(
jsonNode
,
"enabled"
).
asBoolean
();
boolean
accountNonExpired
=
readJsonNode
(
jsonNode
,
"accountNonExpired"
).
asBoolean
();
boolean
credentialsNonExpired
=
readJsonNode
(
jsonNode
,
"credentialsNonExpired"
).
asBoolean
();
boolean
accountNonLocked
=
readJsonNode
(
jsonNode
,
"accountNonLocked"
).
asBoolean
();
User
result
=
new
User
(
username
,
password
,
enabled
,
accountNonExpired
,
credentialsNonExpired
,
accountNonLocked
,
authorities
);
if
(
passwordNode
.
asText
(
null
)
==
null
)
{
result
.
eraseCredentials
();
}
return
result
;
}
private
JsonNode
readJsonNode
(
JsonNode
jsonNode
,
String
field
)
{
return
jsonNode
.
has
(
field
)
?
jsonNode
.
get
(
field
)
:
MissingNode
.
getInstance
();
}
}
youlai-common/common-core/src/main/java/com/youlai/common/constant/SecurityConstants.java
浏览文件 @
a07a3c88
...
...
@@ -15,12 +15,7 @@ public interface SecurityConstants {
/**
* 短信验证码key前缀
*/
String
SMS_CODE_PREFIX
=
"SMS_CODE:"
;
/**
* 接口文档 Knife4j 测试客户端ID
*/
String
TEST_CLIENT_ID
=
"client"
;
String
SMS_CODE_PREFIX
=
"AUTH:SMS_CODE:"
;
/**
* 系统管理 web 客户端ID
...
...
@@ -32,16 +27,14 @@ public interface SecurityConstants {
*/
String
APP_CLIENT_ID
=
"mall-app"
;
/**
* 微信小程序客户端ID
*/
String
WEAPP_CLIENT_ID
=
"mall-weapp"
;
/**
* 用户权限集合缓存前缀
*/
String
USER_PERMS_CACHE_PREFIX
=
"AUTH:USER_PERMS:"
;
/**
* 授权信息中的权限或角色的key
*/
String
AUTHORITIES_CLAIM_NAME_KEY
=
"authorities"
;
}
youlai-common/common-security/src/main/java/com/youlai/common/security/config/ResourceServerConfig.java
浏览文件 @
a07a3c88
...
...
@@ -3,8 +3,10 @@ package com.youlai.common.security.config;
import
cn.hutool.core.collection.CollectionUtil
;
import
cn.hutool.core.convert.Convert
;
import
cn.hutool.json.JSONUtil
;
import
com.youlai.common.constant.SecurityConstants
;
import
lombok.Setter
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.logging.log4j.util.Strings
;
import
org.springframework.boot.context.properties.ConfigurationProperties
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
...
...
@@ -78,10 +80,11 @@ public class ResourceServerConfig {
* @return Converter
* @see JwtAuthenticationProvider#setJwtAuthenticationConverter(Converter)
*/
@Bean
public
Converter
<
Jwt
,
?
extends
AbstractAuthenticationToken
>
jwtAuthenticationConverter
()
{
JwtGrantedAuthoritiesConverter
jwtGrantedAuthoritiesConverter
=
new
JwtGrantedAuthoritiesConverter
();
jwtGrantedAuthoritiesConverter
.
setAuthorityPrefix
(
"ROLE_"
);
jwtGrantedAuthoritiesConverter
.
setAuthoritiesClaimName
(
"authorities"
);
jwtGrantedAuthoritiesConverter
.
setAuthorityPrefix
(
Strings
.
EMPTY
);
jwtGrantedAuthoritiesConverter
.
setAuthoritiesClaimName
(
SecurityConstants
.
AUTHORITIES_CLAIM_NAME_KEY
);
JwtAuthenticationConverter
jwtAuthenticationConverter
=
new
JwtAuthenticationConverter
();
jwtAuthenticationConverter
.
setJwtGrantedAuthoritiesConverter
(
jwtGrantedAuthoritiesConverter
);
...
...
youlai-common/common-security/src/main/java/com/youlai/common/security/util/SecurityUtils.java
浏览文件 @
a07a3c88
package
com.youlai.common.security.util
;
import
cn.hutool.core.collection.CollectionUtil
;
import
cn.hutool.core.convert.Convert
;
import
cn.hutool.core.util.StrUtil
;
import
com.youlai.common.constant.GlobalConstants
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.core.authority.AuthorityUtils
;
import
org.springframework.security.core.context.SecurityContextHolder
;
import
org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken
;
...
...
@@ -13,6 +12,9 @@ import java.util.Map;
import
java.util.Set
;
import
java.util.stream.Collectors
;
/**
* Spring Security 工具类
*/
public
class
SecurityUtils
{
public
static
Long
getUserId
()
{
...
...
@@ -34,15 +36,10 @@ public class SecurityUtils {
public
static
Set
<
String
>
getRoles
()
{
Authentication
authentication
=
SecurityContextHolder
.
getContext
().
getAuthentication
();
var
roles
=
AuthorityUtils
.
authorityListToSet
(
authentication
.
getAuthorities
())
.
stream
()
.
collect
(
Collectors
.
collectingAndThen
(
Collectors
.
toSet
(),
Collections:
:
unmodifiableSet
));
Set
roles
;
if
(
CollectionUtil
.
isNotEmpty
(
authentication
.
getAuthorities
()))
{
roles
=
authentication
.
getAuthorities
()
.
stream
()
.
map
(
item
->
StrUtil
.
removePrefix
(
item
.
getAuthority
(),
"ROLE_"
)).
collect
(
Collectors
.
toSet
());
}
else
{
roles
=
Collections
.
EMPTY_SET
;
}
return
roles
;
}
...
...
youlai-system/system-boot/src/main/java/com/youlai/system/mapper/SysRoleMapper.java
浏览文件 @
a07a3c88
...
...
@@ -16,5 +16,5 @@ public interface SysRoleMapper extends BaseMapper<SysRole> {
* @param roles
* @return
*/
Integer
getMax
imum
DataScope
(
Set
<
String
>
roles
);
Integer
getMax
DataRange
DataScope
(
Set
<
String
>
roles
);
}
youlai-system/system-boot/src/main/java/com/youlai/system/service/SysRoleService.java
浏览文件 @
a07a3c88
...
...
@@ -93,7 +93,7 @@ public interface SysRoleService extends IService<SysRole> {
* @param roles
* @return
*/
Integer
getMax
imum
DataScope
(
Set
<
String
>
roles
);
Integer
getMax
DataRange
DataScope
(
Set
<
String
>
roles
);
}
youlai-system/system-boot/src/main/java/com/youlai/system/service/impl/SysRoleServiceImpl.java
浏览文件 @
a07a3c88
...
...
@@ -206,8 +206,8 @@ public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> impl
* @return
*/
@Override
public
Integer
getMax
imum
DataScope
(
Set
<
String
>
roles
)
{
Integer
dataScope
=
this
.
baseMapper
.
getMax
imum
DataScope
(
roles
);
public
Integer
getMax
DataRange
DataScope
(
Set
<
String
>
roles
)
{
Integer
dataScope
=
this
.
baseMapper
.
getMax
DataRange
DataScope
(
roles
);
return
dataScope
;
}
...
...
youlai-system/system-boot/src/main/java/com/youlai/system/service/impl/SysUserServiceImpl.java
浏览文件 @
a07a3c88
package
com.youlai.system.service.impl
;
import
cn.hutool.core.collection.CollectionUtil
;
import
cn.hutool.core.lang.Assert
;
import
cn.hutool.core.util.StrUtil
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
...
...
@@ -21,6 +22,7 @@ import com.youlai.system.model.query.UserPageQuery;
import
com.youlai.system.model.vo.UserExportVO
;
import
com.youlai.system.model.vo.UserInfoVO
;
import
com.youlai.system.model.vo.UserPageVO
;
import
com.youlai.system.service.SysMenuService
;
import
com.youlai.system.service.SysRoleService
;
import
com.youlai.system.service.SysUserRoleService
;
import
com.youlai.system.service.SysUserService
;
...
...
@@ -55,6 +57,8 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
private
final
RedisTemplate
redisTemplate
;
private
final
SysMenuService
menuService
;
/**
* 获取用户分页列表
*
...
...
@@ -198,9 +202,15 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
UserAuthInfo
userAuthInfo
=
this
.
baseMapper
.
getUserAuthInfo
(
username
);
if
(
userAuthInfo
!=
null
)
{
Set
<
String
>
roles
=
userAuthInfo
.
getRoles
();
// 获取最大范围的数据权限
Integer
dataScope
=
roleService
.
getMaximumDataScope
(
roles
);
userAuthInfo
.
setDataScope
(
dataScope
);
if
(
CollectionUtil
.
isNotEmpty
(
roles
))
{
// 根据角色编码集合获取权限标识集合
Set
<
String
>
perms
=
menuService
.
listRolePerms
(
roles
);
userAuthInfo
.
setPerms
(
perms
);
// 获取最大范围的数据权限(目前设定DataScope越小,拥有的数据权限范围越大,所以获取得到角色列表中最小的DataScope)
Integer
dataScope
=
roleService
.
getMaxDataRangeDataScope
(
roles
);
userAuthInfo
.
setDataScope
(
dataScope
);
}
}
return
userAuthInfo
;
}
...
...
youlai-system/system-boot/src/main/resources/mapper/SysRoleMapper.xml
浏览文件 @
a07a3c88
...
...
@@ -5,7 +5,7 @@
<mapper
namespace=
"com.youlai.system.mapper.SysRoleMapper"
>
<!-- 获取最大范围的数据权限 -->
<select
id=
"getMax
imum
DataScope"
resultType=
"java.lang.Integer"
>
<select
id=
"getMax
DataRange
DataScope"
resultType=
"java.lang.Integer"
>
SELECT
min(data_scope)
FROM
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录