Spring Security 刷新令牌时是否应更新令牌存储上的颁发机构?

piah890a  于 2023-03-02  发布在  Spring
关注(0)|答案(1)|浏览(174)

我正在实现基于角色的Jwt,它在Jwt声明中包含authorities属性。目前,我使用Jwt定制器从上下文中提取身份验证对象,并将其放入Jwt声明中,如下所示。问题是,JwtEncodingContext上的权限不会更改,因为它仅在令牌发布时第一次存储。

@Bean
 fun jwtCustomizer(): OAuth2TokenCustomizer<JwtEncodingContext> {
   return OAuth2TokenCustomizer { context: JwtEncodingContext ->
     val principal: Authentication = context.getPrincipal() // <-- this won't change 
     val user: UserDetailsImpl = principal.principal as UserDetailsImpl
     context.claims.claim("userId", user.getUserId())
     context.claims.claim("authorities", user.getAuthorities())
   }
 }

但是,用户的权限是可以定期更改的,比如用户的权限从“ADMIN”更改为“USER”,但是由于JwtEncodingContext不会更改,所以每次刷新token时,他仍然拥有“ADMIN”的权限,所以我不太清楚如何正确处理这个问题,我能想到的一个办法是通过撤销token来强制用户重新登录。但这种解决方案可能会给用户带来非常糟糕的体验,因为权限可能会在我的系统中定期更改。或者,可能有点肮脏的解决方案是从用户详细信息中查询数据,并将其放在像这样的声明中。

@Bean
 fun jwtCustomizer(): OAuth2TokenCustomizer<JwtEncodingContext> {
   return OAuth2TokenCustomizer { context: JwtEncodingContext ->
     val principal: Authentication = context.getPrincipal() // <-- this won't change 
     val user: UserDetailsImpl = userDetailsRepository.findById(principal.getUserId())
     context.claims.claim("userId", user.getUserId())
     context.claims.claim("authorities", user.getAuthorities())
   }
 }

你知道怎么处理吗?

mlnl4t2r

mlnl4t2r1#

您概述的解决方案是一个可能的选择,在我看来是一个良好的开端。在评论中讨论,我不同意这是一个“肮脏”的解决方案,因为您 * 正在 * 实际使用内置组件,即OAuth2TokenCustomizerUserDetailsService。Spring Security中的内置组件旨在允许您将授权规则和需求集成到框架中。这是你正在尝试做的。如果你有一个可行的解决方案来做这件事,我会说你有一些东西可以建立,你可以随时改进它以后或试验其他方法,如果需要的话。
另一个选项是仅包括roles声明(例如"roles": ["ROLE_ADMIN"]),并在资源服务器中执行权限Map。这样做的好处是始终保持最新,但缺点是需要许多资源服务器查询存储角色到权限Map的数据库,因此无法扩展。如果您对此感兴趣,您将在资源服务器端使用来自spring-security-oauth2-resource-serverJwtGrantedAuthoritiesMapper
如果需要立即撤销,我也推荐使用opaque令牌而不是JWT,如果使用opaque令牌也有类似的支持,尽管在这种情况下最好在authz服务器上定制声明。

相关问题