JSON Web Token jwt使用笔记 token
什么是jwt?
Json web token(JWT)是为了网络应用环境间传递声明而执行的一种基于JSON的开发标准(RFC 7519),该token被设计为紧凑且安全的,特别适用于分布式站点的单点登陆(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。
关于jwt的应用,实现原理,以及具体细节自行百度吧!
java代码测试
pom文件
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.8.1</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.tomcat.util.codec.binary.Base64;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class JwtUtil {
/**
* 加密密文
*/
public static final String JWT_SECRET = "secret";
public static final int JWT_TTL = 60*1000*60*24; //millisecond
/**
* 由字符串生成加密key
*
* @return
*/
public static SecretKey generalKey() {
// 本地的密码解码
byte[] encodedKey = Base64.decodeBase64(JWT_SECRET);
// 根据给定的字节数组使用AES加密算法构造一个密钥
SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
return key;
}
/**
* 创建jwt
*/
public static String createJWT(String id, String issuer, String subject, long ttlMillis, Map<String, Object> claims) throws Exception {
// 指定签名的时候使用的签名算法,也就是header那部分,jjwt已经将这部分内容封装好了。
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
// 生成JWT的时间
long nowMillis = System.currentTimeMillis();
// 生成签名的时候使用的秘钥secret,切记这个秘钥不能外露哦。它就是你服务端的私钥,在任何场景都不应该流露出去。
// 一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了。
SecretKey key = generalKey();
// 下面就是在为payload添加各种标准声明和私有声明了
JwtBuilder builder = Jwts.builder() // 这里其实就是new一个JwtBuilder,设置jwt的body
.setClaims(claims) // 如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的
.setId(id) // 设置jti(JWT ID):是JWT的唯一标识,根据业务需要,这个可以设置为一个不重复的值,主要用来作为一次性token,从而回避重放攻击。
.setIssuedAt(new Date(nowMillis)) // iat: jwt的签发时间
.setIssuer(issuer) // issuer:jwt签发人
.setSubject(subject) // sub(Subject):代表这个JWT的主体,即它的所有人,这个是一个json格式的字符串,可以存放什么userid,roldid之类的,作为什么用户的唯一标志。
.signWith(signatureAlgorithm, key); // 设置签名使用的签名算法和签名使用的秘钥
// 设置过期时间
if (ttlMillis >= 0) {
long expMillis = nowMillis + ttlMillis;
builder.setExpiration(new Date(expMillis));
}
return builder.compact();
}
/**
* 解密jwt
*/
public static Claims parseJWT(String jwt) throws Exception {
SecretKey key = generalKey(); //签名秘钥,和生成的签名的秘钥一模一样
Claims claims = Jwts.parser() //得到DefaultJwtParser
.setSigningKey(key) //设置签名的秘钥
.parseClaimsJws(jwt).getBody(); //设置需要解析的jwt
return claims;
}
public static void main(String[] args) {
String subject ="";
// 创建payload的私有声明(根据特定的业务需要添加,如果要拿这个做验证,一般是需要和jwt的接收方提前沟通好验证方式的)
Map<String, Object> claims = new HashMap<>();
claims.put("id", "1");
claims.put("title", "title");
try {
String jwt = JwtUtil.createJWT(UUID.randomUUID().toString(), "Anson", subject, JWT_TTL, claims);
System.out.println("JWT:" + jwt);
System.out.println("length:"+jwt.length());
System.out.println("解密");
Claims c = JwtUtil.parseJWT("eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIiLCJpc3MiOiJBbnNvbiIsImlkIjoiMSIsInRpdGxlIjoidGl0bGUiLCJleHAiOjE1NzUxNjgxMzMsImlhdCI6MTU3NTA4MTczMywianRpIjoiMzY2MmRmMTgtZTQxMi00OWI3LTlmMGEtMGIyMzhkZWRkMzdiIn0.aIkw4IbiFSsAg4n9BvM-GSdu3Q1jiOyFjxvAW3dvhJY");
System.out.println("id:"+c.getId());
System.out.println("失效时间"+c.getExpiration());
System.out.println("创建时间"+c.getIssuedAt());
System.out.println(c.getSubject());
System.out.println(c.getIssuer());
System.out.println(c.get("id", String.class));
System.out.println(c.get("title", String.class));
System.out.println(c.get("nick_name", String.class));
} catch (Exception e) {
e.printStackTrace();
}
}
}
输出:
JWT:eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIiLCJpc3MiOiJBbnNvbiIsImlkIjoiMSIsInRpdGxlIjoidGl0bGUiLCJleHAiOjE1NzUxNjgxNDgsImlhdCI6MTU3NTA4MTc0OCwianRpIjoiNzg1NTA4YmItMjkxMS00OTgwLTlkOGMtMDU2YTkzNmY1YjA2In0.V_z5yPd8U7Yvl3Z5eENH2V_QXHOld11_zGkDYuEfdgc
length:236
解密
id:3662df18-e412-49b7-9f0a-0b238dedd37b
失效时间Sun Dec 01 10:42:13 CST 2019
创建时间Sat Nov 30 10:42:13 CST 2019
Anson
1
title
null
评论区
请写下您的评论...
猜你喜欢
blog
全文检索笔记
工具
1856
全文检索流程分析图索引库中是如何存储的?数据库的一行数据会存储为一个document对象,一条记录的一列会存储为一个field,不会将数据库的所有数据都存储到索引库。索引是如何创建过程流程图1.分析
file
git & github学习使用笔记
分布式项目管理工具
1220
git&github学习使用笔记
blog
java web图片验证码
工具
2270
javaweb图片验证码1.验证码的作用:防止恶意破解密码、刷票、论坛灌水、刷页。有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登录尝试,实际上使用验证码是现在很多网站通行的方
blog
web浏览器利用本地储存记住用户名
前端(h5)
2066
打开,判断是否存储过用户名---*/ varuName=window.localStorage.getItem('userName'); varpassword=window.localSt
file
ActiveMQ笔记
activemq
1081
ActiveMQ笔记
算法基础
3686
/dependency
dependency
groupIdcn.afterturn/groupId
artifactIdeasypoi-web/artifactId
version4.0.0/ver
框架
8149
上次我们说了spring集成websocket,实现用websocket通讯集成配置连接:http://www.jiajiajia.club/weblog/blog/artical/128下面来模拟
blog
c#对象和json字符串转换
算法基础
1376
c#对象和json字符串转换usingSystem;
usingSystem.Runtime.Serialization.Json;
usingSystem.IO;
usingSystem.Text
最新发表
归档
2018-11
12
2018-12
33
2019-01
28
2019-02
28
2019-03
32
2019-04
27
2019-05
33
2019-06
6
2019-07
12
2019-08
12
2019-09
21
2019-10
8
2019-11
15
2019-12
25
2020-01
9
2020-02
5
2020-03
16
2020-04
4
2020-06
1
2020-07
7
2020-08
13
2020-09
9
2020-10
5
2020-12
3
2021-01
1
2021-02
5
2021-03
7
2021-04
4
2021-05
4
2021-06
1
2021-07
7
2021-08
2
2021-09
8
2021-10
9
2021-11
16
2021-12
14
2022-01
7
2022-05
1
2022-08
3
2022-09
2
2022-10
2
2022-12
5
2023-01
3
2023-02
1
2023-03
4
2023-04
2
2023-06
3
2023-07
4
2023-08
1
2023-10
1
2024-02
1
2024-03
1
2024-04
1
2024-08
1
标签
算法基础
linux
前端
c++
数据结构
框架
数据库
计算机基础
储备知识
java基础
ASM
其他
深入理解java虚拟机
nginx
git
消息中间件
搜索
maven
redis
docker
dubbo
vue
导入导出
软件使用
idea插件
协议
无聊的知识
jenkins
springboot
mqtt协议
keepalived
minio
mysql
ensp
网络基础
xxl-job
rabbitmq
haproxy
srs
音视频
webrtc
javascript
加密算法
目录
没有一个冬天不可逾越,没有一个春天不会来临。最慢的步伐不是跬步,而是徘徊,最快的脚步不是冲刺,而是坚持。