TokenAuthenticationFilter 优化本地缓存的实现

This commit is contained in:
YunaiV 2022-06-26 00:26:22 +08:00
parent ef1096f56a
commit ecd5d607a8
1 changed files with 36 additions and 25 deletions

View File

@ -39,12 +39,18 @@ public class TokenAuthenticationFilter implements GlobalFilter, Ordered {
private final WebClient webClient;
/**
* 登录用户的本地缓存
*
* key1多租户的编号
* key2访问令牌
*/
private final LoadingCache<KeyValue<Long, String>, LoginUser> loginUserCache = CacheUtils.buildAsyncReloadingCache(Duration.ofMinutes(1),
new CacheLoader<KeyValue<Long, String>, LoginUser>() {
@Override
public LoginUser load(KeyValue<Long, String> keyValue) {
String body = checkAccessToken(keyValue.getKey(), keyValue.getValue()).block();
public LoginUser load(KeyValue<Long, String> token) {
String body = checkAccessToken(token.getKey(), token.getValue()).block();
return buildUser(body);
}
@ -70,15 +76,37 @@ public class TokenAuthenticationFilter implements GlobalFilter, Ordered {
}
// 情况二如果有 Token 令牌则解析对应 userIduserTypetenantId 等字段并通过 通过 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);
KeyValue<Long, String> cacheKey = new KeyValue<Long, String>().setKey(tenantId).setValue(token);
LoginUser user = loginUserCache.getUnchecked(cacheKey);
if (user != null) {
SecurityFrameworkUtils.setLoginUser(exchange, user);
return chain.filter(exchange.mutate().request(builder -> SecurityFrameworkUtils.setLoginUserHeader(builder, user)).build());
LoginUser localUser = loginUserCache.getIfPresent(cacheKey);
if (localUser != null) {
return Mono.just(localUser);
}
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) {
@ -88,23 +116,6 @@ public class TokenAuthenticationFilter implements GlobalFilter, Ordered {
.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) {
CommonResult<OAuth2AccessTokenCheckRespDTO> result = JsonUtils.parseObject(body, CHECK_RESULT_TYPE_REFERENCE);
if (result == null || result.isError()) {