| | |
| | | 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 java.io.IOException; |
| | | import java.io.PrintWriter; |
| | | import java.util.ArrayList; |
| | | import java.util.Collections; |
| | | import java.util.List; |
| | | |
| | | /** |
| | |
| | | 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, |