Springboot整合redsi+JWT开发登陆权限


//springboot整合redis+jwt做双token刷新登陆有效时间
前置知识:redis基础和了解Spring的RedisTemplate的基本用法(这里不多说redis本人也是刚刚接触不久)、MD5密码加油加盟(在我前面的博客中有写)、JWT的做登陆权限入门中有解析
思路:用户密码登陆---->JwtInterceptor拦截器(放行登陆请求)--->Controller登陆控制器-->控制器中对密码进行MD5/SHA加盐加密
---->校验用户登陆信息--->正确则调用jwt生成响应头的token令牌并设置有效期为7天,同时以响应头token作为key,
用户名/账号作为value存进redis(redis里面的token是第二个token---代码中采用的是Spring中的RedisTemplate)里面并设置有效时间为2小时,
再以用户账号作为key,tokne作为value 存进redis里面设置有效时间是响应头中token有效时间的一半(作为时间长token重新生成的依据)
然后把生成的响应头token放在响应头中返回前端----->再次访问被拦截器拦截从请求中取出token-->JWT中解析token(判断是否被修改,是否过了响应头token的有效期)--->
如果没过有效期则以token作为key从redis里面取出value,如果value存在证明没过期(如果过期则重新登陆(登陆状态是双token都在有效时间内才为登陆状态))则判断响应头中的token有效时间是否已经过了一半,如何判断?
直接在从私有声明中取出用户名/账号做为key从redis取值,如果值不为null这还没过期则不用重新生成token直接刷新redis中的有效时间,如果值为null则说明响应头中token有效时间已经过半,
则根据用户id从数据库查出改用户的密文重新生成响应头的token同时重新设置redis中的token
下面是主要代码块:
redis工具类:
@Component
public class RedisUtil {
    @Resource
    public StringRedisTemplate stringRedisTemplate;

    public String getKey(String key) {
        return stringRedisTemplate.opsForValue().get(key);
    }

    public void setKey(String key, Object value) {
        stringRedisTemplate.opsForValue().set(key, value.toString());

    }

    public Long getExpire(String key) {
        return stringRedisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    public void setExpire(String key, long timeOut, TimeUnit timeType) {
        stringRedisTemplate.expire(key, timeOut, timeType);
    }

    public Boolean deleteKey(String key) {
        return stringRedisTemplate.delete(key);
    }


}
JWT工具类:
package com.myblog.wj.util;


import com.myblog.wj.entity.BlogUser;
import com.myblog.wj.service.BlogUserService;
import io.jsonwebtoken.*;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.servlet.ServletException;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Component
public class Jwt {
    public  final String JWT_SECRET_KEY= "wangJian";
    public final String JWT_TOKEN_HEADER ="Authorization";
    public  final Long JWT_TOKEN_EXPIRTATION=2L;
    public  static boolean flag=false;//判断redis中token是否过期;
    public  static  Date expireDate=null;
    public  static  Date startDate=null;
    public  static String user_no=null;
   @Resource
RedisUtil redisUtil;
   @Resource
    BlogUserService blogUserService;

    public String CreateToken(BlogUser user){
        //设置token头部
        Mapmap=new HashMap<>();
        map.put("type","JWT");
        map.put("alg","HS256");
        //设置私有声明
        Mapclaims=new HashMap<>();
        claims.put("user_id",user.getUser_id());
        claims.put("user_name",user.getUser_name());
        claims.put("user_no",user.getUser_no());
        //设置响应头token中有效时间为7天//如果连续访问有效时间过半这重新生成token
        Calendar calendar=Calendar.getInstance();
        calendar.setTime(new Date(System.currentTimeMillis()));
        calendar.set(Calendar.DATE,calendar.get(Calendar.DATE)+7);
        expireDate=calendar.getTime();
        String token=Jwts.builder()
                .setClaims(claims)
                .setHeader(map)
                .setIssuedAt(new Date(System.currentTimeMillis()))
                .setExpiration(expireDate)
                .setSubject(user.getUser_id().toString())
                .signWith(SignatureAlgorithm.HS256, JWT_SECRET_KEY)
                .compact();
        System.out.println("token="+token);
        System.out.println("user:"+user);
        //设置redis中token有效时间为2h,同时设置响应头中token是否重新生成(不用用户输入账号密码偷换token从而达到响应头token有效时间刷新)的判断时间超过4天就重新生成token
        redisUtil.setKey(token,user.getUser_name());
        redisUtil.setExpire(token,JWT_TOKEN_EXPIRTATION,TimeUnit.HOURS);
        //作为是否刷新响应头中token的有效时间的依据
        redisUtil.setKey(user.getUser_no(),token);
        redisUtil.setExpire(user.getUser_no(),4,TimeUnit.DAYS);
        System.out.println("取出token="+redisUtil.getKey(token));
        return token;
    }
    //解析token
    public String AnalysisToken(String token) throws ServletException {
        if (token!=null) {
            try {
                Claims claims = Jwts.parser()
                        .setSigningKey(JWT_SECRET_KEY)
                        .parseClaimsJws(token)
                        .getBody();
                System.out.println("来到这里了此时token="+token);
                //刷新redis中token的过期时间同时判断是否重新生成新token
                return RefreshToken(token ,JWT_TOKEN_EXPIRTATION,TimeUnit.HOURS,claims);
            }catch (SignatureException e){
                throw new ServletException("身份验证失败!"+e.getMessage());

            } catch (ExpiredJwtException e) {
                redisUtil.deleteKey(token);
                throw new ServletException("身份已过期");
            }
        }else {
            return null;
        }
    }
    //判断redis中token是否过期
    public  boolean isExpiret(String token){
        String user_name = redisUtil.getKey(token);
        if (user_name == null || "".equals(user_name.trim())) {
            return false;
        }
        return true;
    }
    //刷新redis中的token,同时判断响应头中的token
    public String  RefreshToken(String token , long expiret,TimeUnit timeType,Claims claims){
        user_no=null;
        //判断redis中token是否过期
        flag=isExpiret(token);
        if (flag){
            //如果在redis中的token没过期
            // 判断响应头中的token有效时间 如果响应头中的token有效时间过半则重新生成token
           user_no=claims.get("user_no").toString();
            if(redisUtil.getKey(user_no)==null){
                token=CreateToken(blogUserService.SelectBlogUserByNoAndName(user_no));
                System.out.println("重新生成token="+token);
            }
            redisUtil.setExpire(token, JWT_TOKEN_EXPIRTATION, TimeUnit.HOURS);
            return token;
        }else{
            try {
                throw new ServletException("身份过期!");
            } catch (ServletException e) {
                e.printStackTrace();
            }
            return null;
        }
    }

}
 

你可能感兴趣的:(spring)