java的JWT介绍

什么是 JWT

JWT(JSON Web Token)是一种用于在网络应用之间安全传输信息的开放标准(RFC 7519)。它通常由三部分组成,以紧凑的形式表示,能够在不同的服务或系统之间安全地传递声明(claims)。简单来说,JWT 就像是一张“通行证”,包含了一些必要的信息,并且经过加密处理,接收方可以验证这张“通行证”的真实性和完整性。

JWT 的结构

JWT 由三部分组成,各部分之间用点(.)分隔,格式为 Header.Payload.Signature

1. Header(头部)

Header 通常由两部分组成:令牌的类型(通常是 JWT)和使用的签名算法,如 HMAC SHA256 或 RSA。它是一个 JSON 对象,然后进行 Base64Url 编码。

示例:

{
  "alg": "HS256",
  "typ": "JWT"
}

编码后可能是这样:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

2. Payload(负载)

Payload 包含声明(claims),声明是关于实体(通常是用户)和其他数据的声明。声明分为三种类型:

  • 注册声明:如 iss(发行人)、sub(主题)、aud(受众)等,这些是 JWT 标准中预定义的声明。
  • 公开声明:由各方自由定义。
  • 私有声明:在同意使用的各方之间定义的声明。

示例:

{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022
}

编码后可能是:eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ

3. Signature(签名)

要创建签名部分,需要使用编码后的 Header、编码后的 Payload、一个秘钥(secret)和 Header 中指定的签名算法。例如,使用 HMAC SHA256 算法,签名将按以下方式创建:

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

签名用于验证消息在传输过程中没有被更改,并且在使用私钥签名的情况下,还可以验证 JWT 的发送者的身份。

JWT 的工作流程

  1. 用户登录:用户向服务器发送登录请求,提供用户名和密码。
  2. 服务器验证:服务器验证用户的凭据,如果验证通过,服务器会创建一个 JWT,并将其返回给客户端。
  3. 客户端存储:客户端接收到 JWT 后,通常会将其存储在本地(如 localStorage 或 cookie)。
  4. 后续请求:在后续的请求中,客户端会将 JWT 包含在请求头(如 Authorization: Bearer <JWT>)中发送给服务器。
  5. 服务器验证:服务器接收到请求后,会验证 JWT 的签名和有效性。如果验证通过,服务器会处理请求并返回响应。

示例代码

以下是一个使用 Java 和 jjwt 库生成和验证 JWT 的示例:

添加依赖

如果你使用 Maven,可以在 pom.xml 中添加以下依赖:

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-api</artifactId>
    <version>0.11.5</version>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-impl</artifactId>
    <version>0.11.5</version>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-jackson</artifactId>
    <version>0.11.5</version>
    <scope>runtime</scope>
</dependency>

生成 JWT

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.util.Date;

public class JwtGenerator {
    private static final String SECRET_KEY = "yourSecretKey";

    public static String generateToken(String subject) {
        return Jwts.builder()
               .setSubject(subject)
               .setIssuedAt(new Date(System.currentTimeMillis()))
               .setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 24)) // 过期时间为 24 小时
               .signWith(SignatureAlgorithm.HS256, SECRET_KEY)
               .compact();
    }
}

验证 JWT

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;

public class JwtValidator {
    private static final String SECRET_KEY = "yourSecretKey";

    public static Claims validateToken(String token) {
        return Jwts.parser()
               .setSigningKey(SECRET_KEY)
               .parseClaimsJws(token)
               .getBody();
    }
}

测试代码

public class Main {
    public static void main(String[] args) {
        // 生成 JWT
        String token = JwtGenerator.generateToken("123456");
        System.out.println("Generated JWT: " + token);

        // 验证 JWT
        try {
            Claims claims = JwtValidator.validateToken(token);
            System.out.println("Subject: " + claims.getSubject());
        } catch (Exception e) {
            System.out.println("Invalid JWT: " + e.getMessage());
        }
    }
}

代码解释

  • JwtGenerator.generateToken 方法:使用 Jwts.builder() 创建一个 JWT 构建器,设置主题、签发时间、过期时间,并使用 HMAC SHA256 算法和秘钥进行签名,最后调用 compact() 方法生成 JWT。
  • JwtValidator.validateToken 方法:使用 Jwts.parser() 创建一个 JWT 解析器,设置签名秘钥,调用 parseClaimsJws(token) 方法解析 JWT,如果验证通过,返回 JWT 的负载部分(Claims)。

通过这种方式,你可以在 Java 中方便地生成和验证 JWT,实现安全的信息传输。

Java的JWT目前有以下常见应用场景及成熟案例:

应用场景

  • 单点登录(SSO):在多个相关但独立的系统中,用户只需登录一次,就能访问其他相互信任的系统,无需再次输入用户名和密码。JWT可以在用户登录主系统后生成,然后用户访问其他子系统时,携带该JWT进行身份验证,实现单点登录的效果。
  • 前后端分离项目:在前后端分离架构中,前端和后端是独立开发、部署的。前端通过调用后端提供的API获取数据和执行操作。用户登录后,后端生成JWT返回给前端,前端在后续的请求中,将JWT放在请求头中发送给后端,后端通过验证JWT来确定用户身份和权限,从而返回相应的数据和处理结果。
  • 微服务架构:在微服务架构中,通常包含多个相互独立的微服务。当用户请求涉及多个微服务时,JWT可以在各个微服务之间传递,用于验证用户身份和传递用户相关信息,确保各个微服务能够安全、准确地处理请求。
  • 移动应用与后端交互:移动应用与后端服务器进行通信时,也常使用JWT进行身份验证和授权。用户在移动应用中登录后,后端为其生成JWT,移动应用将JWT存储在本地,后续请求都携带JWT,以便后端识别用户身份,提供相应的服务。

成熟案例

  • Spring Cloud微服务项目:许多采用Spring Cloud构建的微服务项目会使用JWT进行身份认证和授权管理。例如,在一个大型电商微服务系统中,包括用户服务、订单服务、商品服务等多个微服务。用户登录后,系统会生成JWT,该JWT会在用户与各个微服务之间的交互中传递,用于验证用户身份和判断用户是否具有访问相应资源的权限。
  • 大型企业OA系统:一些大型企业的办公自动化(OA)系统采用前后端分离架构,使用JWT实现用户身份认证。员工通过Web端或移动端登录OA系统后,系统会为其生成JWT。员工在进行请假、审批、查看文档等操作时,前端会将JWT携带在请求中发送给后端,后端根据JWT中的信息进行权限验证和业务处理。
  • 开源项目Shiro:Apache Shiro是一个强大且易用的Java安全框架,它支持JWT等多种身份验证方式。在很多基于Shiro框架的项目中,开发人员会利用Shiro对JWT的支持,实现安全的身份认证和授权功能。例如,一些小型的Web应用项目,使用Shiro结合JWT来保护应用的资源,确保只有合法用户能够访问相应的功能和数据。
posted @ 2025-03-06 20:55  皇问天  阅读(359)  评论(0)    收藏  举报