Token的生成与自动续约

一、生成Token前的校验工作

//生成了密钥,CAPTCHA_CODE_KEY = "captcha_codes:",uuid是唯一标识
//在我们登录的时候就已经将UUID+标识符放入了redis缓存中
String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
//去redis中获取了这个值
String captcha = redisCache.getCacheObject(verifyKey);
//删除了密钥,这是验证产生是产生的
redisCache.deleteObject(verifyKey);
//如果没有拿到密钥下的值,说明缓存中的数据过期了
//下面就根据是否有值来走不同的业务
   if (captcha == null)
        {
           
        }
        //验证码跟我们传过去的不一样,用户的验证码输入错误了
        if (!code.equalsIgnoreCase(captcha))
        {
          
        }
//检查密码
        // 用户验证
//下面就可以生成Token了

二、开始生成Token的内容数据

Token的生成与自动续约_第1张图片

Token的生成与自动续约_第2张图片

/**
 * 创建令牌
 * @param loginUser 用户信息
 * @return 令牌
 */
public String createToken(LoginUser loginUser) {
    //重新生成uuid
    String token = IdUtils.fastUUID();
    //将UUID设置为我们的唯一标识
    loginUser.setToken(token);
    //设置用户代理
    setUserAgent(loginUser);
    //刷新令牌
    refreshToken(loginUser);
    //令牌指令加生的uuid
    Map claims = new HashMap<>();
//这里放了令牌前缀
    claims.put(Constants.LOGIN_USER_KEY, token);
    //存放非敏感信息
    claims.put("username",loginUser.getUsername());
    claims.put("nickName",loginUser.getUser().getNickName());
    claims.put("createTime",loginUser.getUser().getCreateTime());
    return createToken(claims);
}

在创建令牌前我们刷新了UserLogin类的过期时间,放到了Redis

/**
 * 刷新令牌有效期
 * @param loginUser 登录信息
 */
public void refreshToken(LoginUser loginUser)
{
    //获取令牌,设置令牌的时间为当前的系统时间
    loginUser.setLoginTime(System.currentTimeMillis());
    //再为令牌增加默认的30分钟
    loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE);
    // 根据uuid将loginUser缓存,拿到用户修改之后的token
    String userKey = getTokenKey(loginUser.getToken());
    //重新将缓存中的用户数据刷新
    redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES);
}

三、开始创建Token

/**
 * 从数据声明生成令牌
 * @param claims 数据声明
 * @return 令牌
 */
private String createToken(Map claims)
{
    //返回令牌
    String token = Jwts.builder()
            .setClaims(claims)
            //在这里生成我们的tokne,同时用我们的签名进行了加密
            //这里面放了姓名,创建时间
            .signWith(SignatureAlgorithm.HS512, secret).compact();
    return token

整体代码如下

/**
 * token验证处理
 *
 * 
 */
@Component
public class TokenService {
    // 令牌自定义标识
    @Value("${token.header}")
    private String header;

    // 令牌秘钥
    @Value("${token.secret}")
    private String secret;

    // 令牌有效期(默认30分钟)
    @Value("${token.expireTime}")
    private int expireTime;

    protected static final long MILLIS_SECOND = 1000;

    protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND;

    private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L;

    @Autowired
    private RedisCache redisCache;

    /**
     * 获取用户身份信息
     *
     * @return 用户信息
     */
    public LoginUser getLoginUser(HttpServletRequest request) {
        // 获取请求携带的令牌
        String token = getToken(request);
        if (StringUtils.isNotEmpty(token)) {
            Claims claims = parseToken(token);
            // 解析对应的权限以及用户信息
            String uuid = (String) claims.get(Constants.LOGIN_USER_KEY);
            String userKey = getTokenKey(uuid);
            LoginUser user = redisCache.getCacheObject(userKey);
            return user;
        }
        return null;
    }

    /**
     * 设置用户身份信息
     */
    public void setLoginUser(LoginUser loginUser)
    {
        if (StringUtils.isNotNull(loginUser) && StringUtils.isNotEmpty(loginUser.getToken()))
        {
            refreshToken(loginUser);
        }
    }

    /**
     * 删除用户身份信息
     */
    public void delLoginUser(String token)
    {
        if (StringUtils.isNotEmpty(token))
        {
            String userKey = getTokenKey(token);
            redisCache.deleteObject(userKey);
        }
    }

    /**
     * 创建令牌
     * @param loginUser 用户信息
     * @return 令牌
     */
    public String createToken(LoginUser loginUser) {
        //重新生成uuid
        String token = IdUtils.fastUUID();
        //将UUID设置为我们的唯一标识
        loginUser.setToken(token);
        //设置用户代理
        setUserAgent(loginUser);
        //刷新令牌
        refreshToken(loginUser);
        //令牌指令加生的uuid
        Map claims = new HashMap<>();
        // LOGIN_USER_KEY = "login_user_key"; 令牌前缀,就是UUID
        claims.put(Constants.LOGIN_USER_KEY, token);
        //存放非敏感信息
        claims.put("username",loginUser.getUsername());
        claims.put("nickName",loginUser.getUser().getNickName());
        claims.put("createTime",loginUser.getUser().getCreateTime());
        return createToken(claims);
    }

    /**
     * 验证令牌有效期,相差不足20分钟,自动刷新缓存
     * @param loginUser
     * @return 令牌
     */
    public void verifyToken(LoginUser loginUser)
    {
        //获取令牌中的过期时间
        long expireTime = loginUser.getExpireTime();
        //获取当前的系统时间
        long currentTime = System.currentTimeMillis();
        //如果二者的时间差小于20分钟
        if (expireTime - currentTime <= MILLIS_MINUTE_TEN)
        {
            refreshToken(loginUser);
        }
    }

    /**
     * 刷新令牌有效期
     * @param loginUser 登录信息
     */
    public void refreshToken(LoginUser loginUser)
    {
        //获取令牌,设置令牌的时间为当前的系统时间
        loginUser.setLoginTime(System.currentTimeMillis());
        //再为令牌增加默认的30分钟
        loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE);
        // 根据uuid将loginUser缓存,拿到用户修改之后的token
        String userKey = getTokenKey(loginUser.getToken());
        //重新将缓存中的用户数据刷新
        redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES);
    }

    /**
     * 设置用户代理信
     * @param loginUser 登录信息
     */
    public void setUserAgent(LoginUser loginUser)
    {
        UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
        String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
        loginUser.setIpaddr(ip);
        loginUser.setLoginLocation(AddressUtils.getRealAddressByIP(ip));
        loginUser.setBrowser(userAgent.getBrowser().getName());
        loginUser.setOs(userAgent.getOperatingSystem().getName());
    }

    /**
     * 从数据声明生成令牌
     * @param claims 数据声明
     * @return 令牌
     */
    private String createToken(Map claims)
    {
        //返回令牌
        String token = Jwts.builder()
                .setClaims(claims)
                //在这里生成我们的tokne,同时用我们的签名进行了加密
                //这里面放了姓名,创建时间
                .signWith(SignatureAlgorithm.HS512, secret).compact();
        return token;
    }

    /**
     * 从令牌中获取数据声明
     *
     * @param token 令牌
     * @return 数据声明
     */
    private Claims parseToken(String token)
    {
        return Jwts.parser()
                .setSigningKey(secret)
                .parseClaimsJws(token)
                .getBody();
    }

    /**
     * 从令牌中获取用户名
     *
     * @param token 令牌
     * @return 用户名
     */
    public String getUsernameFromToken(String token)
    {
        Claims claims = parseToken(token);
        return claims.getSubject();
    }

    /**
     * 获取请求token
     *
     * @param request
     * @return token
     */
    private String getToken(HttpServletRequest request)
    {
        String token = request.getHeader(header);
        if (StringUtils.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX))
        {
            token = token.replace(Constants.TOKEN_PREFIX, "");
        }
        return token;
    }

    private String getTokenKey(String uuid)
    {
        return Constants.LOGIN_TOKEN_KEY + uuid;
    }
}

你可能感兴趣的:(工具类,bootstrap,spring)