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

Posted

技术标签:

【中文标题】如何将一些附加字段添加到此 Spring Boot 服务生成的 JWT 令牌中?【英文标题】:How can I add some additional fields into a JWT token generated by this Spring Boot service? 【发布时间】:2021-12-31 08:55:09 【问题描述】:

我正在开发一个生成 JWT 令牌的 Spring Boot 微服务,我对向生成的令牌中添加其他信息的可能性有以下疑问。

基本上在我的代码中我做了这样的事情(它工作正常):

@Override
public UserDetails loadUserByUsername(String UserId) throws UsernameNotFoundException 
    
    String ErrMsg = "";
    
    if (UserId == null || UserId.length() < 2) 
        ErrMsg = "Nome utente assente o non valido";
        
        logger.warn(ErrMsg);
        
        throw new UsernameNotFoundException(ErrMsg); 
     
    
    User user = this.GetHttpValue(UserId);
    
    if (user == null) 
        ErrMsg = String.format("User %s not found!!", UserId);
        
        logger.warn(ErrMsg);
        
        throw new UsernameNotFoundException(ErrMsg);
    
    
    UserBuilder builder = null;
    
    builder = org.springframework.security.core.userdetails.User.withUsername(user.getEMail());
    builder.password(user.getPswd());
    
    String[] operations = user.getUserTypes().stream()
            .map(UserType::getOperations)
            .flatMap(Set::stream)
            .map(Operation::getName)
            .distinct()
            .toArray(String[]::new);
    
    builder.authorities(operations);
    
    return builder.build();
        

正如你在前面的代码中看到的,我有这个方法返回一个 UserDetails 对象(属于 Spring Security,它是这个类:org.springframework.security.core.userdetails。用户详细信息)。这个 UserDetails 实例是从这个检索到的模型对象开始创建的(它是通过调用 REST 端点来检索的):

User user = this.GetHttpValue(UserId);

基本上,这个 UserDetails 对象用于通过使用前一个 UserDetails 对象的第二种方法生成 JWT 令牌:

private String doGenerateToken(Map<String, Object> claims, UserDetails userDetails) 

    final Date createdDate = clock.now();
    final Date expirationDate = calculateExpirationDate(createdDate);

    return Jwts.builder()
            .setClaims(claims)
            .setSubject(userDetails.getUsername())
            .claim("authorities", userDetails.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()))
            .setIssuedAt(createdDate)
            .setExpiration(expirationDate)
            .signWith(SignatureAlgorithm.HS512, jwtConfig.getSecret().getBytes())
            .compact();

注意: Jwtsio.jsonwebtoken.Jwts

这会生成一个包含以下负载信息的令牌:


  "sub": "xxx@gmail.com",
  "exp": 1637412048,
  "iat": 1637325648,
  "authorities": [
    "ADMIN"
  ]

这是正确的,但是...是否可以在此有效负载中添加更多信息?特别是我需要将一些信息添加到我的 User DTO 对象中,但不添加到之前的 Spring Security UserDetails 实例中。

我按照 Udemy 教程实现了这种行为,现在我有以下疑问。

为什么前面的 doGenerateToken() 方法从 Spring Security UserDetails 实例而不是直接从 User DTO 对象生成令牌(它包含更多有用的信息)。

如果出于某些特定原因使用此 UserDetails 实例而不是我的简单 User DTO 对象,则有一种方法可以将这些信息添加到 UserDetails 实例,然后将这些附加字段放入我的 JWT 令牌中?

【问题讨论】:

为什么在 spring 已经附带 jwt 库 Nimbus 时使用 io.jsonwebtoken.Jwts 【参考方案1】:

您正在将声明映射传递给doGenerateToken 方法。然后将它们作为声明添加到令牌有效负载中。您可以在此地图中添加任何您喜欢的内容来创建令牌。

至于为什么doGenerateToken 方法不使用User DTO 的问题?好吧,如果该方法不是接口的一部分,那么您可以让它接受任何类,对吗?如果您更喜欢使用 User 对象,那么我认为您可以。如果它是一个接口的实现,那么你应该问作者这是什么原因,但人们宁愿在 Spring 中仔细考虑过这些接口,并且有充分的理由为什么它们以这种或另一种方式构建。即使一开始它们看起来很奇怪。

【讨论】:

以上是关于如何将一些附加字段添加到此 Spring Boot 服务生成的 JWT 令牌中?的主要内容,如果未能解决你的问题,请参考以下文章

向 Spring Boot 应用程序添加附加参数

如何在spring boot gradle项目中将时间戳附加到jar?

将应用程序上下文路径附加到 Spring Boot 应用程序中的超链接

文件上传角度 - spring boot - mysql

如何将列表项附加到此 ol? [复制]

和spring cloud/boot 学习如何管理自己的组件