会话跟踪方案中的JWT技术——用于实现登录认证

心已赠人 2024-03-23 23:34 205阅读 0赞
1、会话技术
  • 会话:用户打开浏览器,访问web服务器的资源,会话建立,直到有一方断开连接,会话结束。在一次会话中可以包含多次请求和响应。
  • 会话跟踪:一种维护浏览器状态的方法,服务器需要识别多次请求是否来自于同一浏览器,以便在同一次会话的多次请求间共享数据。
会话跟踪方案:
  • 客户端会话跟踪技术:Cookie
  • 服务端会话跟踪技术:Session
  • 令牌技术
各跟踪方案优缺点:

优点:

  • 简单易用:Cookie 是浏览器内置的机制,使用起来相对简单。
  • 前端控制:可以在前端轻松设置和读取,无需服务器参与,使得某些场景下的状态跟踪更方便。

缺点:

  • 安全性:Cookie 存储在客户端,可能会被篡改或盗取,因此不适合存储敏感信息。
  • 大小限制:每个域名下的 Cookie 数量和总大小都有限制,可能会导致存储不足问题。
  • 跨域问题:Cookie 通常只能在设置它的域名下使用,不方便在不同域名之间共享会话信息。
Session:

优点:

  • 安全性:Session 数据存储在服务器上,相对于 Cookie 更加安全,可以存储敏感信息。
  • 灵活性:可以存储复杂的数据结构,适合存储会话相关的数据。
  • 跨域问题:Session 数据存储在服务器上,因此可以在不同域名之间共享。

缺点:

  • 存储开销:每个会话都需要在服务器上存储相关数据,可能增加服务器的负担。
  • 扩展性:需要使用外部存储或者分布式方案,以支持高负载或多服务器环境。
令牌技术(如JWT):

优点:

  • 无状态:令牌技术基于无状态的原则,服务器无需在后端存储会话数据,适用于分布式架构。
  • 跨平台:令牌可以在不同的平台和服务之间传递,适用于前后端分离的应用。
  • 可扩展性:可以在令牌中包含自定义的信息,适应各种场景的需求。

缺点:

  • 安全性:令牌被篡改可能会导致安全问题,需要采取安全措施如加密和签名。
  • 令牌大小:令牌可能会比传统的会话标识(如Session ID)更大,增加网络传输开销。
  • 处理复杂度:在服务器端需要验证令牌的合法性,可能需要一些额外的代码和操作。
2、JWT技术
1)全称:JSON Web Token

定义了一种简洁的、自包含的格式,用于在通信双方以json数据格式安全的传输信息。由于数字签名的存在,这些信息是可靠的。

2)组成:
  • 第一部分: Header(头),记录令牌类型、签名算法等。例如: {“alg”:”HS256”,”type”:”JWT”)
  • 第二部分: Payload(有效载荷),携带一些自定义信息、默认信息等。例如: (“id”:”1” “username”:”Tom”)
  • 第三部分:Signature(签名),防止Token被篡改、确保安全性。将header、payload,并加入指定秘钥,通过指定签名算法计算而来。10cdc50812c34493aa48a5249e47a34f.png
3)场景:登录认证
  • 登录成功后,生成令牌
  • 后续每个请求,都要携带JWT令牌,系统在每次请求处理之前,先校验令牌,通过后,再处理
4)JWT生成

示例:

  1. @Test
  2. public void testGenJwt(){
  3. Map<String, Object> clamis = new HashMap<>();
  4. clamis.put("age",18);
  5. clamis.put("username","Young");
  6. String jwt= Jwts.builder()
  7. .setClaims(clamis)//自定义内容(载荷)
  8. .signWith(SignatureAlgorithm.HS256,"Young")//签名算法
  9. .setExpiration(new Date(System.currentTimeMillis() + 3600*1000))//有效期设置为一小时
  10. .compact();
  11. System.out.println(jwt);
  12. }

以上代码中,Jwts.builder():这是创建 JWT 令牌的生成器的起始点。可以通过它来逐步配置生成 JWT 所需的各个部分。

然后声明一个clamis对象,这里的 claims 是一个 Map<String, Object>,它包含了我希望在 JWT 的载荷(Payload)中添加的声明(claims)。在 JWT 中,载荷是一组包含有关令牌的信息的键值对。然后我将信息放入clamis中。

而其中的.signWith(SignatureAlgorithm.HS256, "Young"):这是指定如何对 JWT 进行签名的部分。SignatureAlgorithm.HS256 表示使用 HMAC SHA-256 签名算法,Young则是用于签名的密钥。

.setExpiration(new Date(System.currentTimeMillis() + expire)):这里设置了 JWT 的过期时间。这里设置为1小时(毫秒数),用于指定从当前时间开始,多长时间后 JWT 将过期。

.compact():这一步将各个配置组合起来生成最终的 JWT 令牌。

5)JWT解析

示例:

  1. @Test
  2. public void testParseJwt(){
  3. Claims claims = Jwts.parser()
  4. .setSigningKey("Young")//此处放入你所设置的签名密钥
  5. .parseClaimsJws("You JWT")//此处放入生成的jwt密钥
  6. .getBody();
  7. System.out.println(claims);
  8. }

附加:jwt生成和解码工具类:

  1. public class JwtUtils {
  2. private static String signKey = "Young";
  3. private static Long expire = 43200000L;//设置有效期为24小时
  4. /**
  5. * 生成JWT令牌
  6. * @param claims JWT第二部分负载 payload 中存储的内容
  7. * @return
  8. */
  9. public static String generateJwt(Map<String, Object> claims){
  10. String jwt = Jwts.builder()
  11. .addClaims(claims)
  12. .signWith(SignatureAlgorithm.HS256, signKey)
  13. .setExpiration(new Date(System.currentTimeMillis() + expire))
  14. .compact();
  15. return jwt;
  16. }
  17. /**
  18. * 解析JWT令牌
  19. * @param jwt JWT令牌
  20. * @return JWT第二部分负载 payload 中存储的内容
  21. */
  22. public static Claims parseJWT(String jwt){
  23. Claims claims = Jwts.parser()
  24. .setSigningKey(signKey)
  25. .parseClaimsJws(jwt)
  26. .getBody();
  27. return claims;
  28. }
  29. }

注意要添加依赖:

  1. <dependency>
  2. <groupId>io.jsonwebtoken</groupId>
  3. <artifactId>jjwt</artifactId>
  4. <version>0.9.1</version>
  5. </dependency>

发表评论

表情:
评论列表 (有 0 条评论,205人围观)

还没有评论,来说两句吧...

相关阅读

    相关 聊一下会话跟踪技术

    1.1 概述   HTTP 是无状态,无状态是指协议对于事务处理没有记忆能力,不能保存每次客户端提 交的信息,即当服务器返回应答之后,这次事务的所有信息就都丢掉了。如果用