From 29f5825e22f8ed6cc2019511ad75a4939bafb6a8 Mon Sep 17 00:00:00 2001 From: lyfO_o <764716047@qq.com> Date: 星期六, 06 五月 2023 16:00:35 +0800 Subject: [PATCH] 用户token 过滤链判断限制 --- safePlatfrom-out-web/src/main/java/com/gkhy/safePlatform/config/security/TokenAuthenticationFilter.java | 128 ++++++++++++++++++------------------------ 1 files changed, 55 insertions(+), 73 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 1316c2a..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 @@ -10,6 +10,7 @@ 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; @@ -29,6 +30,7 @@ import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Collections; import java.util.List; /** @@ -68,97 +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 accessTokenKey = RedisKeyEnum.authKey(RedisKeyEnum.AUTH_TOKEN, authToken); Object o = redisUtils.get(accessTokenKey); // 2.token是否存在 if (o == null) { - // 是否存在 + // 是否存在 uid未登录 throw new BusinessException(ResultCodes.CLIENT_CREDENTIALS_TOKEN_INVALID); }else{ - Long userId = Long.valueOf(loginUserId); - ContextCacheUser contextCacheUser = JSONObject.parseObject(o.toString(), ContextCacheUser.class); - assert userId.equals(contextCacheUser.getUid()); - if ( !authToken.equals(contextCacheUser.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); - Object oo = redisUtils.get(authoritiesKey); - List<GrantedAuthority> authorities = new ArrayList<>(); - // 4.redis中是否存在 - if (oo != null) { - // 5.存在 - List<ContextCacheAuthority> cacheAuthorities = JSONArray.parseArray(oo.toString(), ContextCacheAuthority.class); - for (ContextCacheAuthority cacheAuthority: cacheAuthorities) { - authorities.add(new SimpleGrantedAuthority(cacheAuthority.getAuthority())); - } - }else { - // 6.不存在=>数据库查询 - ResultVO<String> rpcResultRole = userAccountService.getUserRoleCodeByUserId(userId); - - if (rpcResultRole == null) { - throw new BusinessException(ResultCodes.RPC_RESULT_NULL); - } - if (!ResultCodes.OK.getCode().equals(rpcResultRole.getCode())) { - throw new BusinessException(rpcResultRole.getCode(), rpcResultRole.getMsg()); - } - if (rpcResultRole.getData() == null) { - throw new BusinessException(ResultCodes.RPC_DATA_NULL); - } - if (!(rpcResultRole.getData() instanceof String)) { - throw new BusinessException(ResultCodes.RPC_DATA_TYPE_NOT_MATCH); - } - // role - authorities.add(new SimpleGrantedAuthority("ROLE_" + rpcResultRole.getData().toString())); - - // permission - ResultVO<List<String>> rpcResultPermission = userAccountService.getUserPermissionByUserId(userId); - - if (rpcResultPermission == null) { - throw new BusinessException(ResultCodes.RPC_RESULT_NULL); - } - if (!ResultCodes.OK.getCode().equals(rpcResultPermission.getCode())) { - throw new BusinessException(rpcResultRole.getCode(), rpcResultRole.getMsg()); - } - if (rpcResultPermission.getData() == null) { - throw new BusinessException(ResultCodes.RPC_DATA_NULL); - } - if (!(rpcResultPermission.getData() instanceof List)) { - throw new BusinessException(ResultCodes.RPC_DATA_TYPE_NOT_MATCH); - } - - List<String> permissions = RPCUtils.castList(rpcResultPermission.getData(), String.class); - 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(contextCacheUser,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