欢迎光临我的博客查看最新文章: https://river106.cn
1、简介
JWT,JSON Web Token的简写,是目前比较流行的跨域认证解决方案,
它不是一个具体的技术实现,而更像是一种标准。
2、JWT数据结构
JWT由3部分构成:
- Header(头部)
- Payload(负载)
- Signature(签名)
Header
Header 部分是一个 JSON 对象,描述 JWT 的元数据,通常是下面的样子
{
"alg": "HS256",
"typ": "JWT"
}
alg
属性表示签名的算法(algorithm),默认是 HMAC SHA256(写成 HS256);
typ
属性表示这个令牌(token)的类型(type),JWT 令牌统一写为JWT
。
最后,将上面的 JSON 对象使用 Base64URL 算法转成字符串。
Payload
Payload 部分也是一个 JSON 对象,用来存放实际需要传递的数据。如:
{
"id": "123",
"name": "river"
}
JWT 默认是不加密的,任何人都可以读到,所以不要把秘密信息放在这个部分。
这个 JSON 对象也要使用 Base64URL 算法转成字符串。
Signature
Signature 部分是对前两部分的签名,防止数据篡改。
首先,需要指定一个密钥(secret)。然后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名。
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
算出签名以后,把 Header、Payload、Signature 三个部分拼成一个字符串,每个部分之间用"点"(.
)分隔。
JWT是可以被解码的,所以不要在JWT的Payload中存放私密数据。
3、JWT使用
引入依赖
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
由于我们需要通过jwt生成token,并能通过token解析生成原始数据,所以可以封装成工具类。
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.*;
public class JwtUtils {
private static final String SECRET = "jwt123456";
public static String generateToken(Map<String, Object> claims, Date expireTime) {
return Jwts.builder()
.setClaims(claims)
.signWith(SignatureAlgorithm.HS256, SECRET)
.setExpiration(expireTime)
.compact();
}
public static Map<String, Object> parseToken(String token) {
try {
Claims body = Jwts.parser()
.setSigningKey(SECRET)
.parseClaimsJws(token)
.getBody();
return body;
} catch (ExpiredJwtException e) {
e.printStackTrace();
}
return null;
}
}
在我们做登录鉴权的项目时,服务端生成jwt返回给客户端,客户端可以将jwt储存在Cookie里面,也可以储存在 localStorage。此后,客户端每次与服务器通信,都带上这个jwt。放在 Cookie 里面可以自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP 请求头中。
4、使用JWT需要注意的地方
1、JWT 中的数据默认是不加密的,不加密的情况下,不能将秘密数据写入JWT;
2、一旦JWT签发了,在到期之前始终有效,除非服务器有额外的限制逻辑(如使用redis控制登录session有效期),所以需要设置有效期;
3、为防止泄露,JWT不应该使用HTTP协议明码传输,要使用HTTPS协议传输。