SpringBoot中使用JWT验证登录状态

什么是JWT

全称Java web token,我暂时理解为是一种token的生成规范或者说算法(?)

SpringBoot中的应用

我是用来在项目中验证用户的登录状态

  • 登录的时候生成token,存到浏览器cookie里面,一般都会设置token有效时间,就是登录状态的可持续时间
  • 每次请求request都会带上cookie
  • 拦截器从request里面拿到token,进行验证,通过就放行,否则就跳转到登录页

使用jjwt库


<dependency>
    <groupId>io.jsonwebtokengroupId>
    <artifactId>jjwt-apiartifactId>
    <version>0.11.2version>
dependency>
<dependency>
    <groupId>io.jsonwebtokengroupId>
    <artifactId>jjwt-implartifactId>
    <version>0.11.2version>
    <scope>runtimescope>
dependency>
<dependency>
    <groupId>io.jsonwebtokengroupId>
    <artifactId>jjwt-jacksonartifactId>
    <version>0.11.2version>
    <scope>runtimescope>
dependency>
  1. 生成jwt
/**
 * 生成token  map是登陆个人信息
 * @param map
 * @return
 */
- 下面的SignStr可以是自己设置的,也可以用UUID这种自动生成一个
- map里面就是账号密码之类的登录信息
public static String getToken(Map<String,String> map) throws NoSuchAlgorithmException, InvalidKeyException {
    SecretKey key = Keys.hmacShaKeyFor(SignStr.getBytes(StandardCharsets.UTF_8));  //生成秘钥
    String token = Jwts.builder()
                    .setExpiration(DateUtils.addDays(new Date(),7))  //有效时间7天
                    .setNotBefore(new Date())  //生效时间
                    .setIssuedAt(new Date())  //签发时间
                    .setClaims(map)   //用户登录信息
                    .signWith(key,SignatureAlgorithm.HS256)  //签名
                    .compressWith(CompressionCodecs.DEFLATE)
                    .compact();

    System.out.println("生成token: " + token);
    return token;
}
  1. 验证jwt
/**
 * 验证token的合法性
 * @param token
 */
- 在执行这个方法的时候,如果token验证失败,会报异常
	比较常见几个的的有:
	· ExpiredJwtException token过期异常
	· MalformedJwtException 密钥验证不一致
	· SignatureException 签名异常
    
public static void verify(String token){
    SecretKey key = Keys.hmacShaKeyFor(SignStr.getBytes(StandardCharsets.UTF_8));  //生成秘钥

    Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token).getBody();

}

3、创建token验证拦截器

public class TokenInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("---------进入登录验证拦截器-------------");
        String token = CookieUtil.getCookie(request, "token");
        System.out.println("url:" + request.getRequestURL());
        if (StringUtil.isEmpty(token)) {
            System.out.println("token为空");
            response.sendRedirect("/login-view");
            return false;
        } else {
            try {
                JWTUtils.verify(token);
            } catch (Exception e) {
                System.out.println("token验证失败");
                CookieUtil.deleteCookie(request, response, "token");
                response.sendRedirect("/login-view");
                return false;
            }
        }
        return true;
    }
}

4、配置拦截路径

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addViewControllers(ViewControllerRegistry registry){
        //把login-view跳转到 试图login(login加上前缀后缀(application.propertise配置的mvc)
        registry.addViewController("/login-view").setViewName("../static/start/login.html");
    }

    //登录拦截器JWT
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new TokenInterceptor())
                .addPathPatterns("/**") //拦截所有请求
                .excludePathPatterns("/"
                        ,"/appResource/**"
                        ,"/assets/**"
                        ,"/h5/**"
                        ,"/start/**"
                        ,"/staticFile/**"
                        ,"/templ/**"
                        ,"/favicon.ico"
                        ,"/index.html"
                        ,"/MP_verify_m9OeemkWw7iC1UNd.txt"
                        ,"/login/**"
                        ,"/login-view"); //放行静态资源
    }
}

补充问题

  • 改了密码重新登录

    • 把密码put到负载里面,解析token之后,和数据库里密码做对比,如果修改过了,就让用户重新登录
  • 只要在用登录状态就一直都不失效

    • 检查token的签发时间和生效时间,要是小于某个值,就重新生成token

你可能感兴趣的:(工作记录,spring,boot,java,spring)