在 Spring Boot 微服务的 JWT 令牌生成中设置两个主题

Posted

技术标签:

【中文标题】在 Spring Boot 微服务的 JWT 令牌生成中设置两个主题【英文标题】:Setting two subject in JWT token generation in spring boot microservice 【发布时间】:2018-06-03 04:10:53 【问题描述】:

我正在尝试为我的微服务生成 JWT 令牌。该令牌将使用我的前端应用程序进行服务访问。在这里,我通过添加我的用户名来设置主题。我需要添加用户 ID 和用户名。下面的代码我只通过添加主题“用户名”来生成令牌。

我的代码是,

protected String getToken(String encodedSecret, Users jwtUser)
    return Jwts.builder()
            .setId(UUID.randomUUID().toString())
            .setSubject(jwtUser.getUsername())
            .signWith(SignatureAlgorithm.HS512, encodedSecret)
            .compact();

这里我需要添加两个带有用户 ID 的主题用户名。如何在此处添加两个主题?

【问题讨论】:

【参考方案1】:

您不能拥有两个或多个同名声明:

4. JWT Claims

JWT 声明集表示一个 JSON 对象,其成员是 JWT 传达的声明。 JWT 声明集中的声明名称 必须是唯一的; JWT 解析器必须要么拒绝重复的 JWT 声明名称或使用仅返回词法最后的 JSON 解析器 重复的成员名称 [...]

但是,您可以对用户 ID 使用其他声明:

return Jwts.builder()
           .setId(UUID.randomUUID().toString())
           .setSubject(jwtUser.getUsername())
           .signWith(SignatureAlgorithm.HS512, encodedSecret)
           .claim("user-id", "id goes here")
           .compact();

我可以添加一个对象而不是一个整数吗?喜欢 JSON 吗?

是的,声明值可以是任意 JSON 值,但声明名称必须是字符串:

2. Terminology

[...]

声明名称 声明表示的名称部分。声明名称是 总是一个字符串。**

声明价值 声明表示的价值部分。索赔价值可以是 任何 JSON 值。

[...]

3. JSON Web Token (JWT) Overview

JWT 将一组声明表示为 JSON 对象,该对象被编码为 JWS 和/或 JWE 结构。此 JSON 对象是 JWT 声明集。 [...] JSON 对象包括 零个或多个名称/值对(或成员),其中名称是 字符串和值是任意 JSON 值。这些成员是 JWT 所代表的声明。 [...]

所以你可以定义一个类:

class UserDetails 

    private Integer id;
    private List<String> roles;

    public UserDetails(Integer id, String... roles) 
        this.id = id;
        this.roles = Arrays.asList(roles);
    

    public Integer getId() 
        return id;
    

    public UserDetails setId(Integer id) 
        this.id = id;
        return this;
    

    public List<String> getRoles() 
        return roles;
    

    public UserDetails setRoles(List<String> roles) 
        this.roles = roles;
        return this;
    

然后按如下方式使用:

return Jwts.builder()
           .setId(UUID.randomUUID().toString())
           .setSubject(jwtUser.getUsername())
           .signWith(SignatureAlgorithm.HS512, encodedSecret)
           .claim("user-details", new UserDetails(1, "ROLE_1", "ROLE_2"))
           .compact();
            

它将产生以下有效载荷:


  "jti": "d65b83fd-fafb-4df4-9782-c4700c3c93ff",
  "sub": "joe.doe",
  "user-details": 
    "id": 1,
    "roles": [
      "ROLE_1",
      "ROLE_2"
    ]
  

【讨论】:

那么我如何在这个编码中添加额外的信息。假设我需要通过添加其 ID 来添加角色,例如 1001,2001? 我可以添加一个对象而不是一个整数吗?像 JSON 吗? 是的,我发现更新了。我会尝试。感谢您的回复。

以上是关于在 Spring Boot 微服务的 JWT 令牌生成中设置两个主题的主要内容,如果未能解决你的问题,请参考以下文章

spring boot - 假装客户端发送基本授权标头|将 jwt 令牌从一个微服务传递到另一个微服务

架构微服务 Spring Boot

如何将一些附加字段添加到此 Spring Boot 服务生成的 JWT 令牌中?

微服务 Spring Cloud Gateway + Spring Security LDAP 作为 SSO + JWT - 请求/响应之间丢失令牌

如何使用 Spring Security 实现具有两级令牌认证的 Spring Boot 微服务?

使用 Spring Boot 进行 JWT 身份验证