目录
JWT令牌的使用
1. 需求
在实现系统登录功能的时候,我们需要实现用户完成一次登录之后,在后续的请求中不再需要反复登录,以前我们经常用到的技术是session
- 即用户发出登录的请求到服务器。
- 验证成功之后,创建session对象(用于存储数据)。
- 服务器返回一个session对象的id到浏览器,浏览器以cookie的形式存储到浏览器端
- 后续的浏览器的请求都携带这个cookie访问服务器就可以实现多次请求间的数据共享,包括登录状态
但是使用session存在以下缺点:
- session中与用户的会话数据是保存在服务器的内存中的,当session中的数据越来越大,会降低服务器运行的性能
- session无法用于集群环境,因为session是存储的服务器端的,这样子虽然安全,但集群环境中一般会布置多台服务器,用户在浏览器端二次请求使用的sessionID访问的不是第一次请求的服务器,就无法获取到session中的数据
- session底层是基于cookie实现的,cookie无法实现跨域(域指的是域名,即网址,只要协议、IP地址和端口号任意一个不同即为跨域)且cookie无法在移动端使用,这是浏览器出于安全禁止的。
这时, JWT令牌技术就问世了,令牌技术将上面的问题基本都解决了,如下
- 跨域问题:
jwt令牌是无状态的,jwt令牌的编码所用的信息就有用户信息(如用户名和用户id等非敏感信息),因此,服务器不需要存储跟用户的会话信息,对jwt令牌解析之后,就可以确定该请求是否来自同一端,确保了服务器的安全问题。
在跨域请求中,浏览器会自动检查请求的来源,如果不是同源的请求,会触发跨域安全机制导致请求被阻止。但通过使用令牌技术,可以将令牌作为请求的一部分发送,服务器接收到请求时会验证令牌的有效性,从而允许跨域请求。 - 服务器存储压力:jwt令牌存储在浏览器端
- PC和移动端都可以使用
2. 是什么
jwt令牌本质是一串字符串,由三部分组成,类似"xxx.yyy.zzz",前两部分(xxx.yyy)由json对象经过base64编码而来,“zzz”部分属于签名(通过加密算法和密钥生成的),jwt令牌由编码和加密而来,jwt令牌也可以被解析获取json对象中的信息,解析失败一般会导致程序的报错。
(参考课程笔记:javaweb)JWT的组成: (JWT令牌由三个部分组成,三个部分之间使用英文的点来分割)
-
第一部分:Header(头), 记录令牌类型、签名算法等。 例如:{“alg”:“HS256”,“type”:“JWT”}
-
第二部分:Payload(有效载荷),携带一些自定义信息、默认信息等。 例如:{“id”:“1”,“username”:“Tom”}
-
第三部分:Signature(签名),防止Token被篡改、确保安全性。将header、payload,并加入指定秘钥,通过指定签名算法计算而来。
3. 工作流程
4. 怎么用
-
导入maven坐标,junit不是一定要导入,后续只是用作测试
<dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>test</scope> </dependency>
-
创建令牌(注意密钥的长度要稍微大点)
@Test public void testGetJwt() { //模拟浏览器发请求携带的用户信息 Map<String, Object> claims = new HashMap<>(); claims.put("username", "aimin"); claims.put("password", "123456"); String jwtToken = Jwts.builder() //设置签名加密算法和密钥 .signWith(SignatureAlgorithm.HS256, "aimin") //设置声明,里面可以是一些自定义的信息 .setClaims(claims) //设置token过期时间 .setExpiration(new Date(System.currentTimeMillis() + 3600 * 1000)) //添加JWT 字符串由三部分组成,它们通过句点 . 分隔开来,分别是头部(Header)、载荷(Payload)、签名(Signature)。compact() 方法的作用是将这三部分合并成一个完整的 JWT 字符串,以便在网络传输中使用。 .compact(); System.out.println(jwtToken); }
-
解析令牌
@Test public void testParserJwt(){ Map<String, Object> claims = Jwts.parser() //输入密钥 .setSigningKey("aimin") //输入令牌 .parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJwYXNzd29yZCI6IjEyMzQ1NiIsImV4cCI6MTcxMjUwNTQ0MCwidXNlcm5hbWUiOiJhaW1pbiJ9.2V277eqJo3gxiRgrxM3JbbKku6qez2WgsJ5dCE9kZP8") .getBody(); System.out.println(claims); }
标签:令牌,浏览器,请求,JWT,session,&&,服务器 From: https://blog.csdn.net/m0_63834571/article/details/137522019