【问题标题】:Dynamically changing JWT subject field动态变化的 JWT 主题字段
【发布时间】:2018-02-09 04:39:02
【问题描述】:

我成功地将 JWT 实现为我的 Web 应用程序中的身份验证过滤器。当用户的login 成功时,我正在创建一个新的JWT 并在JWTsub 字段中分配userName。 在随后的请求中,我在JWT sub 字段中使用userName 来识别用户。但是如果用户在应用程序的更新部分更改了他的userName 怎么办。有没有办法,我可以更新JWTsub字段的值?

我在想什么!

我正在考虑在RestController 中获取现有的JWT,在更新userName 之后,我将使用新的userName 更新JWT,然后再次发送回客户端。这很好还是有更好的方法?

【问题讨论】:

    标签: spring-boot spring-security jwt spring-security-oauth2


    【解决方案1】:

    如果您允许您的用户更改他们的用户名,他们还应该有一个不可变的用户 ID,可用于识别与给定用户关联的任何数据或活动。否则,每当用户更改他或她的姓名时,您要么无法审核用户过去的操作,要么必须更新数据库中对该用户名的所有引用。更糟糕的是,如果在数据库中有对旧用户名的引用,而另一个用户使用了该用户名 - 现在由于对用户标识的错误处理,您有一个用户的数据现在与另一个用户相关联。

    话虽如此,sub 声明应该包含这个不可变的用户 ID。您可以为可变用户名创建单独的声明。更改用户名时,您现在只需更改数据库中的单个字段(假设只有 users 表引用此可变用户名)。然后,您可以使用刷新令牌检索包含最新用户名的新令牌,然后您的 API 可以根据需要使用该用户名。

    使用这种方法,您应该注意仅将用户名声明用于显示目的,而不是用于识别登录用户,因为它是可变的。包含用户 ID 的子声明将用于识别用户。

    还需要注意的是,此解决方案不需要特殊逻辑来“更新子声明”。您将使用与为提供的刷新令牌生成令牌相同的逻辑。

    【讨论】:

    • 现在,每当用户更新任何字段时,我都会创建一个新的 JWT,它在其可变的 sub 字段中包含最新的 userName
    【解决方案2】:

    我认为我应该在更新完成后刷新令牌并将刷新的令牌发送回客户端。

    @RequestMapping( value = "/account", method = RequestMethod.POST )
    public ResponseEntity<?> updateAccount( @RequestBody UserDetailsBean userDetailsBean, HttpServletRequest request,
            HttpServletResponse response )
    {
        try
        {
            UserAccessDetails accessDetails = getLoggedInUser();
            UserDetailsBean updatedUserBean = userService.updateAccount(userDetailsBean, accessDetails);
    
            // send updated jwt incase of mobile number update by user
            response.addHeader(SecurityConstants.HEADER_STRING,
                    SecurityConstants.TOKEN_PREFIX + refreshJWT(updatedUserBean.getMobileNumber()));
            return buildResponse(updatedUserBean);
        }
        catch( DataException e )
        {
            return buildError(e);
        }
    }
    
    private String refreshJWT( String subject )
    {
        return Jwts.builder().setSubject((subject))
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
                .signWith(SignatureAlgorithm.HS512, SecurityConstants.SECRET).compact();
    }
    

    这是有效的。如果有人有更清洁和行业标准的方法,请说明。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-12
      相关资源
      最近更新 更多