版权声明:本文为博主yellowcong原创文章,未经博主允许不得转载。 https://blog.csdn.net/yelllowcong/article/details/86169824
通过jwt来进行用户的认证,解决手机端和接口之间的有状态的问题,这种jwt方式,又好也有不好,好处在于没有了状态,坏处是需要更多的带宽和计算资源来做认证,同时,当权限修改后,必须要等到token过期后,才不能用。
jwt原理
仔细辨别会发现它由 A.B.C 三部分组成,这三部分依次是头部(Header)、负载(Payload)、签名(Signature),头部和负载以 JSON 形式存在,这就是 JWT 中的 JSON,三部分的内容都分别单独经过了 Base64 编码,以 . 拼接成一个 JWT Token。
# A部分 加密算法和token类型
#eyJhbGciOiJIUzUxMiJ9
#B部分,负载类容了
#eyJzdWIiOiJjb250ZW50IiwiZXhwIjoxNTQ3MDMzNTA5LCJqdGkiOiIxIiwiaXNzIjoieWVsbG93Y29uZyJ9
#Base64 编码
#j6vpVaHW8lv1FqszG5_2Fm38pB362bS7EMLbPuXGAeD6SxHyS9NxHXTXAyCjXzoekCQz8M5A82CWZW2q8a-srA
eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJjb250ZW50IiwiZXhwIjoxNTQ3MDMzNTA5LCJqdGkiOiIxIiwiaXNzIjoieWVsbG93Y29uZyJ9.j6vpVaHW8lv1FqszG5_2Fm38pB362bS7EMLbPuXGAeD6SxHyS9NxHXTXAyCjXzoekCQz8M5A82CWZW2q8a-srA
登陆到官网https://jwt.io/ ,贴上我们生成的密钥,就可以看到密钥的解密信息了。
jwt标准注册
字段 | 说明 | java实现 |
---|---|---|
iss: | jwt签发者 ,谁签发的token | Jwts.setIssuer(user) |
sub | jwt所面向的用户 | Jwts.setSubject(subject) |
aud | 接收jwt的一方 | |
exp | jwt的过期时间,这个过期时间必须要大于签发时间 | Jwt.setExpirationnew Date(System.currentTimeMillis() + timeLimit)() |
nbf | 定义在什么时间之前,该jwt都是不可用的. | |
iat | jwt的签发时间 | Jwts.setIssuedAt(new Date()) |
jti | jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。 | Jwts.setId(一个string的id) |
java使用 jwt
1. 导入依赖
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
2. 案例代码
代码中,写了两种创建token的方式,第一种方式,直接使用jwt给我们提供的字段来生成token,第二种方案,通过自定义字段,来生成token, 一般我们直接用jwt给我么的字段,就可以满足需求了。
package com.yellowcong.utils;
import java.io.UnsupportedEncodingException;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
public class JwtUtils {
public static final String JWK_SOLT = "yellowcong";
//1000s
//5小时的过期时间
private static final long timeLimit = 5 * 60 * 1000;
public static void main(String[] args) {
byte [] secretKey = getBase64Str(JWK_SOLT);
Map<String,Object> claimsData = new HashMap<String, Object>();
claimsData.put("email", "[email protected]");
claimsData.put("id", "yellowcong");
//第一种
//按照jwt提供的一些参数进行设定
String token = createToken(secretKey,"1","content","yellowcong");
System.out.println(token);
getJwtInfo(token,secretKey);
System.out.println("--------------------");
//第二种方式
//主要是自定义 存储的数据
String token2 = createToken2(secretKey,claimsData);
System.out.println(token2);
getJwtInfo(token2,secretKey);
//过期的token ,当时过期token,就获取不到了
String token3 = "eyJhbGciOiJIUzUxMiJ9.eyJpZCI6InllbGxvd2NvbmciLCJleHAiOjE1NDcwMzUyNjIsImFsZyI6IkhTNTEyIiwiZW1haWwiOiI3MTczNTAzODlAcXEuY29tIn0.vDd0CuaeNuZPn7sIHV9kUeBgrMLYEurxKcEJLeEzyP4KPrVJiTq3mp38ij4lFuDfZGkWREagleGfnAq3ciaK-A";
getJwtInfo(token3,secretKey);
}
private static void getJwtInfo(String token,byte [] secretKey) {
//解析token信息
Claims claims = Jwts.parser()
.setSigningKey(secretKey) //密钥
.parseClaimsJws(token) //解密的字符串
.getBody();
Set<String> keys = claims.keySet();
for(String key:keys) {
System.out.println(key +":" + claims.get(key).toString());
}
//获取加密的信息
System.out.println(claims.getId());
System.out.println(claims.getSubject());
System.out.println(claims.getIssuer());
System.out.println(claims.getExpiration());
System.out.println(claims.get("email"));
System.out.println(claims.get("id"));
System.out.println(claims.getExpiration().getTime() > new Date().getTime());
}
/**
* 获取64编码的字符串
* @param str
* @return
*/
private static byte [] getBase64Str(String str) {
try {
//通过base 64进行编码
return Base64.getEncoder().encode(str.getBytes("utf-8"));
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
private static String createToken(byte [] secretKey,String id,String subject,String user) {
//获取到builder
JwtBuilder builder = Jwts.builder()
.setId(id)
.setIssuer(user) //签发的人
.setSubject(subject) //所接收的人
.setIssuedAt(new Date()) //签发时间
.setExpiration(new Date(System.currentTimeMillis() + timeLimit)) //过期时间
.signWith(SignatureAlgorithm.HS512, secretKey); //签名
return builder.compact();
}
/**
* 这个方法,可以获取到 map集合的数据
* @param secretKey
* @param id
* @param subject
* @param user
* @param data
* @return
*/
private static String createToken2(byte [] secretKey,Map<String,Object> data) {
//获取到builder
JwtBuilder builder = Jwts.builder()
.setClaims(data) //发布的内容是json的情况
.setExpiration(new Date(System.currentTimeMillis() + timeLimit)) //过期时间
.signWith(SignatureAlgorithm.HS512, secretKey); //签名
return builder.compact();
}
}
参考文章
https://www.tuicool.com/articles/3my6zm7
https://www.tuicool.com/articles/BvyuY3B
https://www.tuicool.com/articles/aY3Yz2V