JWT令牌

JWT官网:JSON Web Tokens - jwt.io

一.组成

JWT由三部分组成,每部分使用(.)来分割,三部分分别是:

1)Header(头部),包括令牌的类型以及使用的哈希算法;

2)Payload(负载),存放有效信息(JSON格式),存放的是我们真正想要存放的内容;

3)Signature(签名),作用是防止 Token(主要是 payload) 被篡改,确保安全性。

我们可以在JWT官网参看例子:

我们可以在前面Encoded清晰的看到三部分,Decoded也给出了根据前面编码解码后的内容。

二.使用

1.引入依赖

XML 复制代码
<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-api -->
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-api</artifactId>
    <version>0.11.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-impl -->
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-impl</artifactId>
    <version>0.11.5</version>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-jackson</artifactId> <!-- or jjwt-gson if Gson is preferred -->
    <version>0.11.5</version>
    <scope>runtime</scope>
</dependency>

2.生成令牌

在生成令牌前我们要先生成一个secretString:

java 复制代码
void genKey(){
    Key key = Keys.secretKeyFor(SignatureAlgorithm.HS256);
    String encode = Encoders.BASE64.encode(key.getEncoded());
    System.out.println(encode);
}

我们使用刚刚生成secretString的来生成令牌:

java 复制代码
private static final String secretString = "+8SLJsJyvE/Zvmaq4pHVAjxh7Y+UIgeL+exlD/epzlc=";
//生成密钥
private static Key key = Keys.hmacShaKeyFor(Decoders.BASE64.decode(secretString));
//生成token
public static String genToken(Map<String,Object> map){
    String compact = Jwts.builder()
            .setClaims(map)    //自定义内容
            .signWith(key)    //签名算法
            .compact();
    return compact;
}

出来了设置上面的内容,JWT还可以设置前面发时间和设置过期时间:

java 复制代码
//设置半个小时
long Expiration=30*60*1000;
String compact = Jwts.builder()
    .setClaims(map)    //自定义内容
    .setIssuedAt(new Date())    //设置签发时间
    .setExpiration(new Date(System.currentTimeMillis()+ Expiration)) //设置过期时间
    .signWith(key)    //签名算法
    .compact();

为什么我们要生成一个固定的密钥,而不是每次都生成一个密钥?

因为解码的时候要用到密钥,如果没有生成token的密钥,那么就解不了码了。

注意,一定不要泄露密钥,密钥就是JWT安全性的核心。

3.验证令牌

java 复制代码
//验证token
public static Claims parseToken(String token){
    if(!StringUtils.hasLength(token)){
        return null;
    }
    //创建解析器
    JwtParser build = Jwts.parserBuilder().setSigningKey(key).build();
    Claims claims=null;
    try{
        claims=build.parseClaimsJws(token).getBody();
    }catch (Exception e){
        log.error("token解析错误,e:",e);
    }
    return claims;
}

三.身份验证

服务存储着用户登录信息的令牌(token)发送给客户端,客户端会将收到的token存在localStorage中,此后客户端发送请求(放在HTTP Header中)的时候就会带着这个token。

为什么不讲token放在Cookie中?因为有CSRF风险。

什么是CSRF?CSRF,跨域请求伪造。跨域是指A域名的网站向B域名的网站发送请求。请求伪造主要利用Cookie的自动发送机制:浏览器会自动携带与当前域名匹配的 Cookie 发起请求。当我们进入一个恶意网站B,通过<img>、<iframe>、<form>等标签向A域名网站发起隐式跨域请求(如 GET/POST),浏览器会自动携带A网站的Cookie发送恶意请求。

那为什么使用localStorage不会有CSRF风险?

localStorage属于 浏览器端存储,且严格遵循同源策略(协议、域名、端口均相同)。恶意网站B无法通过JS读取到A网站的localStorage。同时localStorage需前端显式写入请求头。

相关推荐
怪兽源码27 分钟前
基于SpringBoot的选课调查系统
java·spring boot·后端·选课调查系统
恒悦sunsite33 分钟前
Redis之配置只读账号
java·redis·bootstrap
梦里小白龙39 分钟前
java 通过Minio上传文件
java·开发语言
人道领域39 分钟前
javaWeb从入门到进阶(SpringBoot事务管理及AOP)
java·数据库·mysql
sheji52611 小时前
JSP基于信息安全的读书网站79f9s--程序+源码+数据库+调试部署+开发环境
java·开发语言·数据库·算法
毕设源码-邱学长1 小时前
【开题答辩全过程】以 基于Java Web的电子商务网站的用户行为分析与个性化推荐系统为例,包含答辩的问题和答案
java·开发语言
摇滚侠1 小时前
Java项目教程《尚庭公寓》java项目从开发到部署,技术储备,MybatisPlus、MybatisX
java·开发语言
€8111 小时前
Java入门级教程24——Vert.x的学习
java·开发语言·学习·thymeleaf·数据库操作·vert.x的路由处理机制·datadex实战
Mr_star_galaxy2 小时前
【JAVA】经典图书管理系统的实现
java
昊坤说不出的梦2 小时前
【实战】监控上下文切换及其优化方案
java·后端