改了两天的bug,一个JWT解决了。。。

274 阅读2分钟

文章目录

写在前面

JWT(JSON Web Token),看到Token,估计都能猜出他是干啥的了,对,就是用来登录验证的,为啥会聊到JWT呢,之前我做登录验证用的是Cookie和Session,感觉没啥问题,现在我要对我的新闻博客项目做一个版本更新,也就是更新为前后端分离的,这样一改,Cookie不行了,查阅了点资料,并问了问老师,才明白,原来是浏览器为了安全起见,不支持第三方的Cookie了,被迫,把登录验证改用了JWT。

如何使用

学以致用,如何在我们的代码中使用JWT呢,很简单,只需要引入JWT的依赖就可以了,JWT能干什么呢,JWT可以把你需要传的信息封装到一个由.分割的字符串中,当我们进行登录验证的时候,只需要对该字符串验证即可。

<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.10.3</version>
</dependency>

引入之后,我们就可以使用JWT提供的API了,为了方便起见,我们一般会封装一个JWTUtils工具类。

public class JWTUtils {
    private static String SIGN = "TOKEN!@FE123";

    /**
     * 传入payload信息,生成token,默认保存7天
     * @param map
     * @return
     */
    public static String getToken(Map<String, String> map) {

        JWTCreator.Builder builder = JWT.create();
        map.forEach((k,v) -> {
            builder.withClaim(k,v);
        });

        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.DATE,7);
        builder.withExpiresAt(instance.getTime());
        return builder.sign(Algorithm.HMAC256(SIGN));
    }

    /**
     * 验证token
     * @param token
     */
    public static void verify(String token) {
        JWT.require(Algorithm.HMAC256(SIGN)).build().verify(token);
    }

    /**
     * 获取token中的信息
     * @param token
     * @return
     */
    public static DecodedJWT getToken(String token) {
        return JWT.require(Algorithm.HMAC256(SIGN)).build().verify(token);
    }

}

该工具类的使用也很nice,如果我们要把用户的一些信息封装起来,放到header里响应给前端。

Map<String, String> payload = new HashMap<>();
payload.put("userId",String.valueOf(user.getUserId()));
payload.put("username",user.getUsername());
payload.put("headUrl",user.getHeadUrl());
payload.put("userType",String.valueOf(user.getUserType()));

String token = JWTUtils.getToken(payload);
response.addHeader("token",token);

而当我们要对用户进行验证的时候,只需要调用verify方法

String token = request.getHeader("token");
try {
    JWTUtils.verify(token);// 验证令牌
    return true;
} catch (Exception e) {
    System.out.println(e.getMessage());
}
return false;

还有一个重要的点
由于是前后端分离的,在进行配置跨域访问的时候,我们还需要指定一下那个header里的token

 /**
     * 配置跨域访问
     * @return
     */
    private CorsConfiguration corsConfig() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();

        corsConfiguration.addAllowedOrigin("*");// 同源配置,*表示任何请求都视为同源,若需指定ip和端口可以改为如“localhost:8080”,多个以“,”分隔;
        corsConfiguration.addAllowedHeader("*"); // header,允许哪些header
        corsConfiguration.addAllowedMethod("*"); // 允许的请求方法,PSOT、GET、PUT等
        corsConfiguration.addExposedHeader("token");// 拓展header 浏览器放过redponse的token 不然跨域登录收不到token
        corsConfiguration.setAllowCredentials(true);// 允许浏览器携带cookie

        return corsConfiguration;
    }
    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", corsConfig());
        return new CorsFilter(source);
    }

写在后面

很多问题的解决方案,并不是你不会,而是你不知道。