JWT,Java Web Token,通过 JSON 形式作为 Web 应用中的令牌,用于在各方之间安全地将信息作为 JSON 对象传输,在数据传输过程中还可以完成数据加密、签名等相关处理
JWT 的作用如下:

http 协议本身是一种无状态协议,这就意味着如果用户向我们的应用提供了用户名和密码进行认证,那么下次请求时还需再作一次认证。因为根据 http 协议,我们并不知道是哪个用户发出的请求,所以为了让应用能识别是哪个用户发出的请求,我们只能在服务存储一份用户登录的信息,这份登录信息会在响应传递给浏览器,告诉其保存为 cookie,以便下次请求时发送回来,这样我们就能识别请求来自哪个用户了

通常 JWT 如下所示:xxxxx.yyyyy.zzzzz
标头(Header):标头一般由两部分组成:令牌的类型和所使用的签名算法,标头使用 Base64 编码
{
"alg":"HS256",
"typ":"JWT"
}
有效负载(payload):令牌的第二部分是有效负载,其中包含声明。声明是有关实体(通常是用户)和其他数据的声明。同样使用 Base64 编码。不建议放入用户的敏感信息
{
"sub":"12345678",
"name":"john",
"admin":true,
...
}
签名(Signature):Signature 需要使用编码后的 Header 和 Payload 以及我们提供的一个密钥,然后使用 Header 中指定签名算法,进行签名。签名的作用是保证 JWT 没有被篡改过,如:HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload),secret)
客户端收到服务端发送的 token 后,再次请求服务端需要带上 token,此时 token 包含三部分:经过 Base64 编码的 Header、经过 Base64 编码的 Payload 和加密后的签名,服务端用自己保存的 secret 与客户端发送的 Header、Payload 运算,如果结果和客户端带回来的签名不一致,则验证失败
引入依赖
com.auth0
java-jwt
3.4.0
生成 token
Calendar instance = Calendar.getInstance();
instance.add(Calendar.SECOND, 20);
Map map = new HashMap();
String token = JWT.create().withHeader(map) // header
.withClaim("userId", 21) // payload
.withClaim("username", "yeeq")
.withExpiresAt(instance.getTime()) // 指定令牌的过期时间
.sign(Algorithm.HMAC256("FAWF2#!F@")); // 签名,并指定密钥
根据令牌和签名解析数据
// 创建验证对
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256("FAWF2#!F@")).build();
// 解码后的信息
DecodedJWT verify = jwtVerifier.verify("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2MDAyNTQ4NzIsInVzZXJJZCI6MjEsInVzZXJuYW1lIjoieWVlcSJ9.jo_6gKThSXUcEfH1e9bu7at9lm2zmdupwiYvMUWopls");
System.out.println(verify.getClaim("userId").asInt());
System.out.println(verify.getClaim("username").asString());
常见异常信息:
SignatureVerificationException:签名不一致异常TokenExpiredException:令牌过期异常AlgorithmMismatchException:算法不匹配异常InvalidClaimException:失效的 payload 异常一般结合拦截器或者网关完成认证
public class JWTUtils {
private static final String SIGN = "FAWF2#!F@";
/**
* 生成 token
* @param map payload 的信息
* @return token
*/
public static String getToken(Map map) {
Calendar instance = Calendar.getInstance();
instance.add(Calendar.DATE, 7);
JWTCreator.Builder builder = JWT.create();
// 创建 payload
map.forEach((k, v) -> {
builder.withClaim(k, v);
});
String token = builder.withExpiresAt(instance.getTime()) // 指定令牌的过期时间
.sign(Algorithm.HMAC256(SIGN)); // 签名,并指定密钥
return token;
}
/**
* 验证 token 的合法性
* @param token token
*/
public static void verifyJWT(String token) {
JWT.require(Algorithm.HMAC256(SIGN)).build().verify(token);
}
/**
* 获取 token 的信息
* @return token 的信息
*/
public static DecodedJWT getTokenInfo(String token) {
DecodedJWT verify = JWT.require(Algorithm.HMAC256(SIGN)).build().verify(token);
return verify;
}
}
登录查看全部
参与评论
手机查看
返回顶部