Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
Y
yudao-cloud
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
hblj
yudao-cloud
Commits
ecd5d607
提交
ecd5d607
authored
6月 25, 2022
作者:
YunaiV
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
TokenAuthenticationFilter 优化本地缓存的实现
上级
ef1096f5
隐藏空白字符变更
内嵌
并排
正在显示
1 个修改的文件
包含
36 行增加
和
25 行删除
+36
-25
TokenAuthenticationFilter.java
...ao/gateway/filter/security/TokenAuthenticationFilter.java
+36
-25
没有找到文件。
yudao-gateway/src/main/java/cn/iocoder/yudao/gateway/filter/security/TokenAuthenticationFilter.java
浏览文件 @
ecd5d607
...
@@ -39,12 +39,18 @@ public class TokenAuthenticationFilter implements GlobalFilter, Ordered {
...
@@ -39,12 +39,18 @@ public class TokenAuthenticationFilter implements GlobalFilter, Ordered {
private
final
WebClient
webClient
;
private
final
WebClient
webClient
;
/**
* 登录用户的本地缓存
*
* key1:多租户的编号
* key2:访问令牌
*/
private
final
LoadingCache
<
KeyValue
<
Long
,
String
>,
LoginUser
>
loginUserCache
=
CacheUtils
.
buildAsyncReloadingCache
(
Duration
.
ofMinutes
(
1
),
private
final
LoadingCache
<
KeyValue
<
Long
,
String
>,
LoginUser
>
loginUserCache
=
CacheUtils
.
buildAsyncReloadingCache
(
Duration
.
ofMinutes
(
1
),
new
CacheLoader
<
KeyValue
<
Long
,
String
>,
LoginUser
>()
{
new
CacheLoader
<
KeyValue
<
Long
,
String
>,
LoginUser
>()
{
@Override
@Override
public
LoginUser
load
(
KeyValue
<
Long
,
String
>
keyValue
)
{
public
LoginUser
load
(
KeyValue
<
Long
,
String
>
token
)
{
String
body
=
checkAccessToken
(
keyValue
.
getKey
(),
keyValue
.
getValue
()).
block
();
String
body
=
checkAccessToken
(
token
.
getKey
(),
token
.
getValue
()).
block
();
return
buildUser
(
body
);
return
buildUser
(
body
);
}
}
...
@@ -70,15 +76,37 @@ public class TokenAuthenticationFilter implements GlobalFilter, Ordered {
...
@@ -70,15 +76,37 @@ public class TokenAuthenticationFilter implements GlobalFilter, Ordered {
}
}
// 情况二,如果有 Token 令牌,则解析对应 userId、userType、tenantId 等字段,并通过 通过 Header 转发给服务
// 情况二,如果有 Token 令牌,则解析对应 userId、userType、tenantId 等字段,并通过 通过 Header 转发给服务
return
getLoginUser
(
exchange
,
token
).
flatMap
(
user
->
{
if
(
user
==
null
)
{
return
chain
.
filter
(
exchange
);
}
// 设置登录用户
SecurityFrameworkUtils
.
setLoginUser
(
exchange
,
user
);
// 将 user 并设置到 login-user 的请求头,使用 json 存储值
ServerWebExchange
newExchange
=
exchange
.
mutate
().
request
(
builder
->
SecurityFrameworkUtils
.
setLoginUserHeader
(
builder
,
user
)).
build
();
return
chain
.
filter
(
newExchange
);
});
}
private
Mono
<
LoginUser
>
getLoginUser
(
ServerWebExchange
exchange
,
String
token
)
{
// 从缓存中,获取 LoginUser
Long
tenantId
=
WebFrameworkUtils
.
getTenantId
(
exchange
);
Long
tenantId
=
WebFrameworkUtils
.
getTenantId
(
exchange
);
KeyValue
<
Long
,
String
>
cacheKey
=
new
KeyValue
<
Long
,
String
>().
setKey
(
tenantId
).
setValue
(
token
);
KeyValue
<
Long
,
String
>
cacheKey
=
new
KeyValue
<
Long
,
String
>().
setKey
(
tenantId
).
setValue
(
token
);
LoginUser
user
=
loginUserCache
.
getUnchecked
(
cacheKey
);
LoginUser
localUser
=
loginUserCache
.
getIfPresent
(
cacheKey
);
if
(
user
!=
null
)
{
if
(
localUser
!=
null
)
{
SecurityFrameworkUtils
.
setLoginUser
(
exchange
,
user
);
return
Mono
.
just
(
localUser
);
return
chain
.
filter
(
exchange
.
mutate
().
request
(
builder
->
SecurityFrameworkUtils
.
setLoginUserHeader
(
builder
,
user
)).
build
());
}
}
return
checkAccessToken
(
cacheKey
.
getKey
(),
token
)
.
flatMap
((
Function
<
String
,
Mono
<
Void
>>)
body
->
chain
.
filter
(
buildNewServerWebExchange
(
exchange
,
cacheKey
,
body
)));
// 处理请求的结果
// 缓存不存在,则请求远程服务
return
checkAccessToken
(
tenantId
,
token
).
flatMap
((
Function
<
String
,
Mono
<
LoginUser
>>)
body
->
{
LoginUser
remoteUser
=
buildUser
(
body
);
if
(
remoteUser
!=
null
)
{
// 非空,则进行缓存
loginUserCache
.
put
(
cacheKey
,
remoteUser
);
return
Mono
.
just
(
remoteUser
);
}
return
Mono
.
empty
();
});
}
}
private
Mono
<
String
>
checkAccessToken
(
Long
tenantId
,
String
token
)
{
private
Mono
<
String
>
checkAccessToken
(
Long
tenantId
,
String
token
)
{
...
@@ -88,23 +116,6 @@ public class TokenAuthenticationFilter implements GlobalFilter, Ordered {
...
@@ -88,23 +116,6 @@ public class TokenAuthenticationFilter implements GlobalFilter, Ordered {
.
retrieve
().
bodyToMono
(
String
.
class
);
.
retrieve
().
bodyToMono
(
String
.
class
);
}
}
private
ServerWebExchange
buildNewServerWebExchange
(
ServerWebExchange
exchange
,
KeyValue
<
Long
,
String
>
cacheKey
,
String
body
)
{
// 1.1 解析 User
LoginUser
user
=
buildUser
(
body
);
// 1.2 校验 Token 令牌失败,则直接返回
if
(
user
==
null
)
{
return
exchange
;
}
// 2. 设置到缓存
loginUserCache
.
put
(
cacheKey
,
user
);
// 3.1 设置登录用户
SecurityFrameworkUtils
.
setLoginUser
(
exchange
,
user
);
// 3.2 将 user 并设置到 login-user 的请求头,使用 json 存储值
return
exchange
.
mutate
().
request
(
builder
->
SecurityFrameworkUtils
.
setLoginUserHeader
(
builder
,
user
)).
build
();
}
private
LoginUser
buildUser
(
String
body
)
{
private
LoginUser
buildUser
(
String
body
)
{
CommonResult
<
OAuth2AccessTokenCheckRespDTO
>
result
=
JsonUtils
.
parseObject
(
body
,
CHECK_RESULT_TYPE_REFERENCE
);
CommonResult
<
OAuth2AccessTokenCheckRespDTO
>
result
=
JsonUtils
.
parseObject
(
body
,
CHECK_RESULT_TYPE_REFERENCE
);
if
(
result
==
null
||
result
.
isError
())
{
if
(
result
==
null
||
result
.
isError
())
{
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论