当前位置: 首页 > news >正文

java 拦截器-用户无操作超时退出利用Redis

1、授权过滤,只要实现AuthConfigAdapter接口
2、利用Redis token超时时间,用户访问后台续时

效果
在这里插入图片描述

@Component
public class AuthFilter implements Filter {private static Logger logger = LoggerFactory.getLogger(AuthFilter.class);@Autowiredprivate AuthConfigAdapter authConfigAdapter;@Autowired(required = false)private HttpHandler httpHandler;@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {HttpServletRequest req = (HttpServletRequest) request;HttpServletResponse resp = (HttpServletResponse) response;List<String> excludePathPatterns = authConfigAdapter.excludePathPatterns();// 如果匹配不需要授权的路径,就不需要校验是否需要授权if (CollectionUtil.isNotEmpty(excludePathPatterns)) {for (String excludePathPattern : excludePathPatterns) {AntPathMatcher pathMatcher = new AntPathMatcher();if (pathMatcher.match(excludePathPattern, req.getRequestURI())) {chain.doFilter(req, resp);return;}}}String accessToken = req.getHeader("Authorization");String sysType = req.getHeader("SysType");if (StrUtil.isBlank(accessToken)) {logger.error("{} : {}", ResponseEnum.UNAUTHORIZED, req.getRequestURI());httpHandler.printServerResponseToWeb(ServerResponseEntity.fail(ResponseEnum.UNAUTHORIZED));return;}if(StrUtil.isBlank(sysType)){logger.error("{} : {}", ResponseEnum.UNAUTHORIZED, req.getRequestURI());httpHandler.printServerResponseToWeb(ServerResponseEntity.fail(ResponseEnum.UNAUTHORIZED));return;}// 校验token,并返回用户信息ServerResponseEntity<UserInfoInTokenBO> userInfoInTokenVoServerResponseEntity = TokenSecurity.checkToken(accessToken);if (!userInfoInTokenVoServerResponseEntity.isSuccess()) {logger.error("{} : {}", ServerResponseEntity.transform(userInfoInTokenVoServerResponseEntity), req.getRequestURI());httpHandler.printServerResponseToWeb(ServerResponseEntity.transform(userInfoInTokenVoServerResponseEntity));return;}if(userInfoInTokenVoServerResponseEntity.getData().getSysType() != Integer.parseInt(sysType)){httpHandler.printServerResponseToWeb(ServerResponseEntity.fail(ResponseEnum.UNAUTHORIZED));return;}AuthUserContext.set(BeanUtil.copyProperties(userInfoInTokenVoServerResponseEntity.getData(), UserInfoInTokenBO.class));try {chain.doFilter(req, resp);} finally {AuthUserContext.clean();}}
}@Component
@RefreshScope
public class TokenSecurity {private static final Logger logger = LoggerFactory.getLogger(TokenSecurity.class);private static RedisTemplate<Object, Object> redisTemplate = null;private static StringRedisTemplate stringRedisTemplate;public TokenSecurity(RedisTemplate<Object, Object> redisTemplate, StringRedisTemplate stringRedisTemplate) {TokenSecurity.redisTemplate = redisTemplate;TokenSecurity.stringRedisTemplate = stringRedisTemplate;}public static ServerResponseEntity<UserInfoInTokenBO> checkToken(String accessToken) {ServerResponseEntity<UserInfoInTokenBO> userInfoByAccessTokenResponse = getUserInfoByAccessToken(accessToken, true);if (!userInfoByAccessTokenResponse.isSuccess()) {return ServerResponseEntity.transform(userInfoByAccessTokenResponse);}return ServerResponseEntity.success(userInfoByAccessTokenResponse.getData());}public static ServerResponseEntity<UserInfoInTokenBO> getUserInfoByAccessToken(String accessToken, boolean needDecrypt) {if (StrUtil.isBlank(accessToken)) {return ServerResponseEntity.showFailMsg("accessToken is blank");}String realAccessToken;if (needDecrypt) {ServerResponseEntity<String> decryptTokenEntity = decryptToken(accessToken);if (!decryptTokenEntity.isSuccess()) {return ServerResponseEntity.transform(decryptTokenEntity);}realAccessToken = decryptTokenEntity.getData();}else {realAccessToken = accessToken;}UserInfoInTokenBO userInfoInTokenBO = (UserInfoInTokenBO) redisTemplate.opsForValue().get(getAccessKey(realAccessToken));if (userInfoInTokenBO == null) {return ServerResponseEntity.fail(ResponseEnum.CLEAN_TOKEN);}String refreshToken = stringRedisTemplate.opsForValue().get(CacheNames.REFRESH_TO_ACCESS + userInfoInTokenBO.getMobile());if (StrUtil.isBlank(refreshToken)) {return ServerResponseEntity.fail(ResponseEnum.CLEAN_TOKEN);}// 存在则token续时7200秒redisTemplate.opsForValue().getAndExpire(getAccessKey(realAccessToken), 7200L, TimeUnit.SECONDS);return ServerResponseEntity.success(userInfoInTokenBO);}public static String getAccessKey(String accessToken) {return CacheNames.ACCESS + accessToken;}private static ServerResponseEntity<String> decryptToken(String data) {String decryptStr;String decryptToken;try {decryptStr = Base64.decodeStr(data);decryptToken = decryptStr.substring(0,32);// 创建token的时间,token使用时效性,防止攻击者通过一堆的尝试找到aes的密码,虽然aes是目前几乎最好的加密算法long createTokenTime = Long.parseLong(decryptStr.substring(32,45));// token的过期时间int expiresIn = getExpiresIn();long second = 1000L;if (System.currentTimeMillis() - createTokenTime > expiresIn * second) {return ServerResponseEntity.fail(ResponseEnum.TOKEN_ERROR);}}catch (Exception e) {logger.error(e.getMessage());return ServerResponseEntity.fail(ResponseEnum.TOKEN_ERROR);}// 防止解密后的token是脚本,从而对redis进行攻击,uuid只能是数字和小写字母if (!PrincipalUtil.isSimpleChar(decryptToken)) {return ServerResponseEntity.fail(ResponseEnum.TOKEN_ERROR);}return ServerResponseEntity.success(decryptToken);}private static int getExpiresIn() {// 3600秒int expiresIn = 3600;expiresIn = expiresIn * 24;return expiresIn;}
}

相关文章:

  • 【智能算法应用】模拟退火算法求解多车型车辆路径问题HFVRP
  • 在CSDN上成长的感悟,你的粉丝长啥样?
  • DEM、DSM和DTM之间的区别及5米高程数据获取
  • DragonKnight CTF2024部分wp
  • 缓存归纳总结1
  • go语言泛型Generic最佳实践 --- slices包
  • Unity 代码实现Animator开始和结束播放动画回调
  • 代码审计--一道简单的文件包含题目的多种利用方式
  • Jenkins + github 自动化部署配置
  • 二十九篇:构建未来:信息系统的核心框架与应用
  • Laravel(Lumen8) + Supervisor 实现多进程redis消息队列
  • 大一久富农机实习与商业思维学习计划
  • IS-IS DIS
  • Android:OkHttp网络请求框架的使用
  • 【二叉树】LeetCode.144:二叉树的前序遍历(小细节把握)
  • Angularjs之国际化
  • CSS中外联样式表代表的含义
  • es6(二):字符串的扩展
  • IP路由与转发
  • JavaScript对象详解
  • java中具有继承关系的类及其对象初始化顺序
  • JS基础之数据类型、对象、原型、原型链、继承
  • LeetCode29.两数相除 JavaScript
  • magento 货币换算
  • NLPIR语义挖掘平台推动行业大数据应用服务
  • NSTimer学习笔记
  • 从伪并行的 Python 多线程说起
  • 给自己的博客网站加上酷炫的初音未来音乐游戏?
  • 猫头鹰的深夜翻译:Java 2D Graphics, 简单的仿射变换
  • 悄悄地说一个bug
  • 小程序滚动组件,左边导航栏与右边内容联动效果实现
  • 在Docker Swarm上部署Apache Storm:第1部分
  • 深度学习之轻量级神经网络在TWS蓝牙音频处理器上的部署
  • # SpringBoot 如何让指定的Bean先加载
  • # 利刃出鞘_Tomcat 核心原理解析(八)-- Tomcat 集群
  • #DBA杂记1
  • (160)时序收敛--->(10)时序收敛十
  • (C#)一个最简单的链表类
  • (ibm)Java 语言的 XPath API
  • (pytorch进阶之路)扩散概率模型
  • (一)80c52学习之旅-起始篇
  • ****三次握手和四次挥手
  • .NET 4.0中使用内存映射文件实现进程通讯
  • .NET DataGridView数据绑定说明
  • .NET 给NuGet包添加Readme
  • .NET中winform传递参数至Url并获得返回值或文件
  • @Async 异步注解使用
  • @NotNull、@NotEmpty 和 @NotBlank 区别
  • [8] CUDA之向量点乘和矩阵乘法
  • [bzoj1901]: Zju2112 Dynamic Rankings
  • [C][数据结构][树]详细讲解
  • [C++] 如何使用Visual Studio 2022 + QT6创建桌面应用
  • [C++]四种方式求解最大子序列求和问题
  • [CVPR2021]Birds of a Feather: Capturing Avian Shape Models from Images
  • [Invalid postback or callback argument]昨晚调试程序时出现的问题,MARK一下