TokenAuthenticationFilter 优化本地缓存的实现

This commit is contained in:
YunaiV 2022-06-26 00:26:22 +08:00
parent ef1096f56a
commit ecd5d607a8

View File

@ -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 {
} }
// 情况二如果有 Token 令牌则解析对应 userIduserTypetenantId 等字段并通过 通过 Header 转发给服务 // 情况二如果有 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); 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 {
.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()) {