123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
- package com.caimei.config;
- import com.caimei.components.RedisService;
- import com.caimei.utils.JwtUtil;
- import org.aspectj.lang.JoinPoint;
- import org.aspectj.lang.annotation.Aspect;
- import org.aspectj.lang.annotation.Before;
- import org.aspectj.lang.annotation.Pointcut;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.stereotype.Component;
- import org.springframework.web.context.request.RequestContextHolder;
- import org.springframework.web.context.request.ServletRequestAttributes;
- import javax.servlet.http.HttpServletRequest;
- /**
- * 把切面类加入到IOC容器中
- * 所有请求都会更新redis存token的时间
- *
- * @author : Charles
- * @date : 2020/3/17
- */
- @Component
- @Aspect
- public class GlobalTokenAspect {
- @Value("${caimei.oldapi}")
- private String oldApi;
- private RedisService redisService;
- @Autowired
- public void setRedisService(RedisService redisService) {
- this.redisService = redisService;
- }
- /**
- * 定义一个切入点 我这里是从controller切入
- */
- @Pointcut("execution(public * com.caimei.controller..*.*(..))")
- public void pointCut() {
- }
- /**
- * 前置通知
- * 在进入方法前执行 可以对参数进行限制或者拦截
- * 通常在这边做日志存储存到数据库中
- * @param joinPoint
- * @throws Throwable
- */
- @Before("pointCut()")
- public void before(JoinPoint joinPoint) throws Throwable {
- ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
- HttpServletRequest request = attributes.getRequest();
- String token = request.getHeader("X-Token");
- String cacheToken = null!=token ? String.valueOf(redisService.get(token)) : null;
- // Redis过期后会得到"null"值,所以需判断字符串"null"
- if (cacheToken != null && cacheToken.length() != 0 && !"null".equals(cacheToken)) {
- if (JwtUtil.isVerify(cacheToken)) {
- /* String mobileOrEmail = JwtUtil.parseTokenAud(cacheToken);*/
- int userId = JwtUtil.parseTokenUid(cacheToken);
- // 刷新token
- tokenRefresh(token, userId);
- }
- }
- }
- /**
- * JWT Token续签:
- * 业务逻辑:登录成功后,用户在未过期时间内继续操作,续签token。
- * 登录成功后,空闲超过过期时间,返回token已失效,重新登录。
- * 实现逻辑:
- * 1.登录成功后将token存储到redis里面(这时候k、v值一样都为token),并设置过期时间为token过期时间
- * 2.当用户请求时token值还未过期,则重新设置redis里token的过期时间。
- * 3.当用户请求时token值已过期,但redis中还在,则JWT重新生成token并覆盖v值(这时候k、v值不一样了),然后设置redis过期时间。
- * 4.当用户请求时token值已过期,并且redis中也不存在,则用户空闲超时,返回token已失效,重新登录。
- */
- public boolean tokenRefresh(String token, Integer userID) {
- String cacheToken = String.valueOf(redisService.get(token));
- // 过期后会得到"null"值,所以需判断字符串"null"
- if (cacheToken != null && cacheToken.length() != 0 && !"null".equals(cacheToken)) {
- // 校验token有效性
- if (!JwtUtil.isVerify(cacheToken)) {
- // 生成token
- String newToken = JwtUtil.createToken(userID);
- // 将token存入redis,并设置超时时间
- redisService.set(token, newToken, JwtUtil.getExpireTime());
- } else {
- // 重新设置超时时间
- redisService.set(token, cacheToken, JwtUtil.getExpireTime());
- }
- return true;
- }
- return false;
- }
- }
|