动态更改 JWT 主题字段
Dynamically changing JWT subject field
我在我的 Web 应用程序中成功地将 JWT 实现为身份验证过滤器。当用户的 login
成功时,我正在创建一个新的 JWT
并在 JWT
的 sub
字段中分配 userName
。
在后续请求中,我在 JWT
sub
字段中使用 userName
来标识用户。但是,如果用户在应用程序的更新部分更改了他的 userName
怎么办。有没有办法,我可以更新 JWT
中 sub
字段的值?
我在想什么!
我正在考虑在 RestController
中获取现有的 JWT
,在更新 userName
之后,我将使用新的 userName
更新 JWT
并再次发送回客户端。这样好还是有更好的方法?
我想我应该在更新完成后刷新令牌并将刷新的令牌发回客户端。
@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();
}
这是有效的。如果有人有更清洁的行业标准方法,请说明。
如果您允许您的用户更改他们的用户名,他们还应该有一个 immutable 用户 ID,可用于识别与给定用户相关的任何数据或 activity。否则,每当用户更改他或她的名字时,您将失去审计用户过去行为的能力,或者您将不得不更新数据库中对该用户名的所有引用。更糟糕的是,如果数据库中有对旧用户名的引用,而另一个用户使用了该用户名——现在您拥有来自一个用户的数据,由于对用户标识的处理不正确,现在与另一个用户相关联。
话虽如此,子声明应包含此 immutable 用户 ID。您可以为 mutable 用户名创建一个单独的声明。更改用户名时,您现在只需更改数据库中的一个字段(假设只有用户 table 引用此 mutable 用户名)。然后,您可以使用刷新令牌检索一个新令牌,其中包含最新的用户名,然后您的 API 可以根据需要使用该用户名。
使用这种方法时,您应该注意仅将用户名声明用于显示目的,而不是用于识别登录用户,因为它是 mutable。包含用户 ID 的子声明将用于识别用户。
同样重要的是要注意,此解决方案不需要针对 "updating the sub claim." 的特殊逻辑,您将使用与为提供的刷新令牌生成令牌相同的逻辑。
我在我的 Web 应用程序中成功地将 JWT 实现为身份验证过滤器。当用户的 login
成功时,我正在创建一个新的 JWT
并在 JWT
的 sub
字段中分配 userName
。
在后续请求中,我在 JWT
sub
字段中使用 userName
来标识用户。但是,如果用户在应用程序的更新部分更改了他的 userName
怎么办。有没有办法,我可以更新 JWT
中 sub
字段的值?
我在想什么!
我正在考虑在 RestController
中获取现有的 JWT
,在更新 userName
之后,我将使用新的 userName
更新 JWT
并再次发送回客户端。这样好还是有更好的方法?
我想我应该在更新完成后刷新令牌并将刷新的令牌发回客户端。
@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();
}
这是有效的。如果有人有更清洁的行业标准方法,请说明。
如果您允许您的用户更改他们的用户名,他们还应该有一个 immutable 用户 ID,可用于识别与给定用户相关的任何数据或 activity。否则,每当用户更改他或她的名字时,您将失去审计用户过去行为的能力,或者您将不得不更新数据库中对该用户名的所有引用。更糟糕的是,如果数据库中有对旧用户名的引用,而另一个用户使用了该用户名——现在您拥有来自一个用户的数据,由于对用户标识的处理不正确,现在与另一个用户相关联。
话虽如此,子声明应包含此 immutable 用户 ID。您可以为 mutable 用户名创建一个单独的声明。更改用户名时,您现在只需更改数据库中的一个字段(假设只有用户 table 引用此 mutable 用户名)。然后,您可以使用刷新令牌检索一个新令牌,其中包含最新的用户名,然后您的 API 可以根据需要使用该用户名。
使用这种方法时,您应该注意仅将用户名声明用于显示目的,而不是用于识别登录用户,因为它是 mutable。包含用户 ID 的子声明将用于识别用户。
同样重要的是要注意,此解决方案不需要针对 "updating the sub claim." 的特殊逻辑,您将使用与为提供的刷新令牌生成令牌相同的逻辑。