From cd02923a7ce1ffa004b3abbb7af67ab6173dd99d Mon Sep 17 00:00:00 2001
From: zf <1603559716@qq.com>
Date: Mon, 25 Mar 2024 10:59:40 +0800
Subject: [PATCH] Merge branch 'master' of https://sinanoaq.cn:8888/r/safePlatform-out into zf
---
safePlatfrom-out-web/src/main/java/com/gkhy/safePlatform/config/security/TokenAuthenticationFilter.java | 120 +++++++++++++++++++++++++++++++++--------------------------
1 files changed, 67 insertions(+), 53 deletions(-)
diff --git a/safePlatfrom-out-web/src/main/java/com/gkhy/safePlatform/config/security/TokenAuthenticationFilter.java b/safePlatfrom-out-web/src/main/java/com/gkhy/safePlatform/config/security/TokenAuthenticationFilter.java
index 874b46f..9a880a9 100644
--- a/safePlatfrom-out-web/src/main/java/com/gkhy/safePlatform/config/security/TokenAuthenticationFilter.java
+++ b/safePlatfrom-out-web/src/main/java/com/gkhy/safePlatform/config/security/TokenAuthenticationFilter.java
@@ -2,13 +2,18 @@
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
-import com.gkhy.safePlatform.account.rpc.apimodel.UserAccountService;
-import com.gkhy.safePlatform.commons.co.CacheUser;
+import com.gkhy.safePlatform.account.rpc.apimodel.AccountAuthService;
+import com.gkhy.safePlatform.account.rpc.apimodel.AccountAuthService;
+import com.gkhy.safePlatform.commons.co.ContextCacheAuthority;
+import com.gkhy.safePlatform.commons.co.ContextCacheUser;
import com.gkhy.safePlatform.commons.enums.RedisKeyEnum;
import com.gkhy.safePlatform.commons.enums.ResultCodes;
import com.gkhy.safePlatform.commons.exception.BusinessException;
+import com.gkhy.safePlatform.commons.utils.RPCUtils;
+import com.gkhy.safePlatform.commons.utils.RequestContextHolder;
import com.gkhy.safePlatform.commons.utils.StringUtils;
import com.gkhy.safePlatform.commons.vo.ResultVO;
+import com.gkhy.safePlatform.config.redis.RedisUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
@@ -25,6 +30,7 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
/**
@@ -36,7 +42,9 @@
@Autowired
private TokenConfig tokenConfig;
@DubboReference(check = false)
- private UserAccountService userAccountService;
+ private AccountAuthService userAccountService;
+ @Autowired
+ private RedisUtils redisUtils;
@@ -53,12 +61,8 @@
chain.doFilter(req, resp);
} catch (BusinessException e) {
// 返回异常
- this.writeJSON(req, resp, new ResultVO<>(e.getError()));
- } catch (Exception e) {
- e.printStackTrace();
- this.writeJSON(req, resp, new ResultVO<>(ResultCodes.SERVER_ERROR));
+ this.writeJSON(req, resp, new ResultVO<>(e.getCode(),e.getMessage()));
}
-
}
@@ -66,67 +70,77 @@
private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest req,HttpServletResponse resp) {
// header获取token
String authToken = req.getHeader(tokenConfig.getHeader());
- String loginUserId = req.getHeader(tokenConfig.getLoginUserHeader());
-
if(authToken != null) {
- // header 传入 userId
- if (StringUtils.isBlank(loginUserId)) {
- throw new BusinessException(ResultCodes.CLIENT_CREDENTIALS_LACK);
- }
// 登录成功时,会将权限数据存入redis
// 这里是验证获取权限信息
// 1.从redis中获取对应该用户的权限信息
- String accessTokenKey = RedisKeyEnum.authKey(RedisKeyEnum.AUTH_TOKEN, loginUserId);
- String o = userAccountService.getValueByKeyFromRedis(accessTokenKey);
+ String accessTokenKey = RedisKeyEnum.authKey(RedisKeyEnum.AUTH_TOKEN, authToken);
+ Object o = redisUtils.get(accessTokenKey);
// 2.token是否存在
if (o == null) {
- // 是否存在
- throw new BusinessException(ResultCodes.CLIENT_CREDENTIALS_SIGN_INVALID);
+ // 是否存在 uid未登录
+ throw new BusinessException(ResultCodes.CLIENT_CREDENTIALS_TOKEN_INVALID);
}else{
- Long userId = Long.valueOf(loginUserId);
- CacheUser cacheUser = JSONObject.parseObject(o, CacheUser.class);
- assert userId.equals(cacheUser.getUserId());
- if ( !authToken.equals(cacheUser.getAccessToken())) {
- throw new BusinessException(ResultCodes.CLIENT_CREDENTIALS_TOKEN_INVALID);
+ // todo 可以不转换,建议rpc传入string
+ String uid = o.toString();
+ Long userId = Long.valueOf(uid);
+ String accessUserKey = RedisKeyEnum.authKey(RedisKeyEnum.AUTH_USER, userId);
+ // 这里不做用户信息的token判断 放入登录
+ Long expireSecondsLeft = redisUtils.getExpireTime(accessTokenKey);
+ // 60m 内请求则续期 时长为原本的有效时间
+ if (expireSecondsLeft != null && 0L < expireSecondsLeft && expireSecondsLeft < 60 * 60) {
+ // 重置token:uid
+ redisUtils.resetKeyExpireTime(accessTokenKey, tokenConfig.getExpiration());
+ // 重置uid:userInfo
+ redisUtils.resetKeyExpireTime(accessUserKey, tokenConfig.getExpiration());
}
-
- // 3.redis获取权限
- String authoritiesKey = RedisKeyEnum.authKey(RedisKeyEnum.AUTH_AUTHORITIES, userId);
- String oo = userAccountService.getValueByKeyFromRedis(authoritiesKey);
- List<GrantedAuthority> authorities;
- // 4.redis中是否存在
- if (oo != null) {
- // 5.存在
- authorities = JSONArray.parseArray(oo, GrantedAuthority.class);
- }else {
- authorities = new ArrayList<>();
- // 6.不存在=>数据库查询
- String roleCode = userAccountService.getUserRoleCodeByUserId(userId);
- // role
- authorities.add(new SimpleGrantedAuthority("ROLE_" + roleCode));
-
- // permission
- List<String> permissions = userAccountService.getUserPermissionByUserId(userId);
- for (String permission : permissions) {
- SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(permission);
- authorities.add(simpleGrantedAuthority);
- }
+ // 获取用户信息
+ Object oo = redisUtils.get(accessUserKey);
+ // 初始化
+ ContextCacheUser contextCacheUser = null;
+ if (oo == null) {
+ // 业务逻辑上是不会空的
+ // 实际操作可能会手动清空
+ ResultVO<ContextCacheUser> rpcResultVo = userAccountService.getCacheUserDetailByUid(userId);
+ // 调用rpc返回的数据 没有token 所以得至少续上这次token
+ contextCacheUser = this.getRpcResult(rpcResultVo);
+ // 因为手动清空等原因,可能会丢失其他token数据,就不去一一搜索这个uid的token了
+ contextCacheUser.setAccessToken(Collections.singletonList(authToken));
+ }else{
+ // 正常的实际场景必定会走这里
+ // 推荐用jackson
+ contextCacheUser = JSONObject.parseObject(oo.toString(), ContextCacheUser.class);
}
-
+ // threadLocal存入用户信息
+ RequestContextHolder.contextUserLocal.set(contextCacheUser);
// security对象中存入登陆者信息
- return new UsernamePasswordAuthenticationToken(userId,authToken,authorities);
+ return new UsernamePasswordAuthenticationToken(contextCacheUser, authToken, contextCacheUser.getAuthorities());
}
-
-
-
-
-
-
}
return null;
}
+ /**
+ * 获取rpc 返回的用户数据
+ *
+ * @param rpcResultVo rpc返回数据
+ * @return 用户准备缓存的数据
+ */
+ private ContextCacheUser getRpcResult(ResultVO<ContextCacheUser> rpcResultVo) {
+ if (!rpcResultVo.getCode().equals(ResultCodes.OK.getCode())) {
+ throw new BusinessException(rpcResultVo.getCode(), rpcResultVo.getMsg());
+ }
+ if (rpcResultVo.getData() == null) {
+ throw new BusinessException(ResultCodes.RPC_DATA_NULL);
+ }
+ if (rpcResultVo.getData() instanceof ContextCacheUser) {
+ return (ContextCacheUser) rpcResultVo.getData();
+ } else {
+ throw new BusinessException(ResultCodes.RPC_DATA_TYPE_NOT_MATCH);
+ }
+
+ }
protected void writeJSON(HttpServletRequest req,
--
Gitblit v1.9.2