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

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

优点:

  • 简单易用: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,并加入指定秘钥,通过指定签名算法计算而来。
3)场景:登录认证
  • 登录成功后,生成令牌
  • 后续每个请求,都要携带JWT令牌,系统在每次请求处理之前,先校验令牌,通过后,再处理
 4)JWT生成

示例:

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

        以上代码中,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解析

示例:

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

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

public class JwtUtils {

    private static String signKey = "Young";
    private static Long expire = 43200000L;//设置有效期为24小时

    /**
     * 生成JWT令牌
     * @param claims JWT第二部分负载 payload 中存储的内容
     * @return
     */
    public static String generateJwt(Map<String, Object> claims){
        String jwt = Jwts.builder()
                .addClaims(claims)
                .signWith(SignatureAlgorithm.HS256, signKey)
                .setExpiration(new Date(System.currentTimeMillis() + expire))
                .compact();
        return jwt;
    }

    /**
     * 解析JWT令牌
     * @param jwt JWT令牌
     * @return JWT第二部分负载 payload 中存储的内容
     */
    public static Claims parseJWT(String jwt){
        Claims claims = Jwts.parser()
                .setSigningKey(signKey)
                .parseClaimsJws(jwt)
                .getBody();
        return claims;
    }
}

注意要添加依赖:

        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>

猜你喜欢

转载自blog.csdn.net/LuoluoluoluoYan/article/details/132316142
今日推荐