Skip to content
v1
文档/SDKs/部署

JWT 令牌生成规范

JWT 由接入方的业务服务端签发,再下发给已登录的客户端用于 IMSDK 登录。令牌遵循 RFC 7519,采用 HS256 算法签名。

应用密钥与用户 ID

在管理后台的“应用密钥”中获取同一组 AccessKeyAccessSecret

配置用途
AccessKey写入 JWT Header 的 kid,用于定位应用密钥;不是 App ID
AccessSecret作为 HS256 的签名密钥,直接使用原始字符串,不进行 Base64 解码
接入方系统的用户 ID写入 JWT Payload 的 sub,使用字符串类型

HS256 是签名算法,不会加密 Header 或 Payload。AccessSecret 只能保存在业务服务端,不能写入 JWT、客户端代码或日志。业务服务端应根据当前已认证用户确定 sub,不能直接信任客户端任意传入的用户 ID。

json
{
  "alg": "HS256",
  "typ": "JWT",
  "kid": "YOUR_ACCESS_KEY"
}
字段说明
alg签名算法,固定为 HS256
typ令牌类型,固定为 JWT
kid必填,应用密钥中的 AccessKey

Payload

json
{
  "sub": "user_10001",
  "name": "张三",
  "avatar": "https://example.com/avatar.png",
  "iat": 1788825600,
  "jti": "d63e9154-91bb-4c40-aab7-c6c26d394a11",
  "exp": 1788825900
}
字段说明
sub必填,接入方系统的用户 ID,字符串类型
name可选,用户昵称
avatar可选,用户头像 URL
iat签发时间,Unix 时间戳,单位为
jtiJWT 唯一标识,用于防重放;每次签发生成新值,保证有效期内唯一
exp过期时间,Unix 时间戳,单位为,必须晚于 iat

nameavatar 字段存在且对应用户不存在时,会自动创建用户。

签发时请同时设置 iatjtiexp。示例采用 5 分钟有效期;上面的时间仅用于展示结构,实际签发必须使用当前时间。登录重试或重新获取令牌时重新签发 JWT,不要重复使用旧的 jti,并保持业务服务端时钟同步。

Java 示例

示例使用 JDK 17 和 Auth0 java-jwt,通过 withKeyId 设置 kid,通过 Algorithm.HMAC256 使用 AccessSecret 签名。

1. 添加 Maven 依赖

新建目录,在其中保存以下 pom.xml;已有 Maven 项目只需添加其中的依赖:

xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>example</groupId>
    <artifactId>imsdk-jwt-demo</artifactId>
    <version>1.0.0</version>
    <dependencies>
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>4.6.0</version>
        </dependency>
    </dependencies>
</project>

2. 生成令牌

在同一目录保存 ImSdkJwtDemo.java

java
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;

import java.time.Instant;
import java.util.Date;
import java.util.UUID;

public class ImSdkJwtDemo {
    public static String createToken(String accessKey, String accessSecret, String userId) {
        if (accessKey == null || accessKey.isBlank()
                || accessSecret == null || accessSecret.isBlank()
                || userId == null || userId.isBlank()) {
            throw new IllegalArgumentException("AccessKey、AccessSecret 和用户 ID 不能为空");
        }
        Instant now = Instant.now();
        return JWT.create()
                .withKeyId(accessKey)
                .withSubject(userId)
                .withIssuedAt(Date.from(now))
                .withJWTId(UUID.randomUUID().toString())
                .withExpiresAt(Date.from(now.plusSeconds(300)))
                // 如需自动创建用户,可在此添加真实昵称和头像:
                // .withClaim("name", "张三")
                // .withClaim("avatar", "https://example.com/avatar.png")
                .sign(Algorithm.HMAC256(accessSecret));
    }

    public static void main(String[] args) {
        String accessKey = System.getenv("IM_ACCESS_KEY");
        String accessSecret = System.getenv("IM_ACCESS_SECRET");
        // 仅演示:实际业务应使用服务端当前已认证用户的 ID。
        String userId = "user_10001";
        String token = createToken(accessKey, accessSecret, userId);

        // 本地自检:验证签名、用户 ID 和关键字段,不输出令牌或密钥。
        DecodedJWT jwt = JWT.require(Algorithm.HMAC256(accessSecret))
                .withSubject(userId)
                .build()
                .verify(token);
        if (!accessKey.equals(jwt.getKeyId())
                || !"HS256".equals(jwt.getAlgorithm())
                || !"JWT".equals(jwt.getType())
                || jwt.getId() == null
                || jwt.getIssuedAt() == null || jwt.getExpiresAt() == null
                || jwt.getExpiresAt().getTime() - jwt.getIssuedAt().getTime() != 300_000L) {
            throw new IllegalStateException("JWT 字段校验失败");
        }
        System.out.println("JWT 已生成,本地验签与字段校验通过");
        // 实际接入时,通过业务接口把 token 返回给当前已认证的客户端。
    }
}

3. 运行

在业务服务端环境中设置 IM_ACCESS_KEYIM_ACCESS_SECRET,分别对应同一组应用密钥。仅做本地自检时可使用虚构测试值;IMSDK 登录必须使用管理后台的有效应用密钥。

在上述文件所在目录执行:

bash
mvn dependency:copy-dependencies -DoutputDirectory=lib
javac -encoding UTF-8 -cp "lib/*" ImSdkJwtDemo.java
java -cp ".:lib/*" ImSdkJwtDemo

Windows 下最后一条命令的类路径使用分号:java -cp ".;lib/*" ImSdkJwtDemo

运行成功会显示 JWT 已生成,本地验签与字段校验通过。这仅验证本地签发结果,实际接入仍需将返回的令牌交给 IMSDK 完成登录验证。