我们正在使用资源所有者凭据授权类型(在 security-config.xml
中使用 oauth2:password
。让我们用这个场景来解释我的困境:
- Bob 的创建权限为
ROLE_USER
- Bob 尝试访问受 oauth2 保护的资源
- Bob 使用官方移动应用程序访问它,因此客户端凭据是正确的
- Bob 的访问 token 已创建并存储在
TokenStore
中,以他的username
、client_id
和scope
为关键字>。 (参见 DefaultAuthenticationKeyGenerator.java) - Bob 的手机尝试使用此访问 token 调用 protected 服务,但这些服务要求用户拥有
ROLE_MOBILE_USER
的权限
。 - Bob 联系数据库所有者并将
ROLE_MOBLE_USER
添加到他在数据库中的用户。 - Bob 尝试获取另一个访问 token ,但
DefaultTokenServices
返回给他相同的、无效的访问 token 。 - 利用他的新
权限
的唯一方法是等到他的旧访问 token 过期,这样他就可以获得具有正确权限
的新访问 token 。
有很多方法可以解决这个问题。
首先,将 ROLE_MOBILE_USER
添加到 Bob 权限的管理应用程序随后可以清除数据库中的所有访问 token 和授权。通过这种方式,DefaultTokenServices
将创建一个新的具有正确权限的序列化为他的新 OAuth2Authentication。然而,此时我们可能不希望 Administration webapp 关注 OAuth(至少现在不)。如果可能的话,我们希望管理应用程序的关注点尽可能简洁,并且现在不依赖于 oauth。
我们可以将 DELETE
方法暴露给 /oauth/access_token
端点,并告诉移动应用程序尝试删除该访问 token 并重新请求一个,以防万一存储的 authorities
是陈旧的。不过,这感觉更像是一种解决方法。
最后,我可以在我自己定义的 AuthenticationKeyGenerator
中序列化 authorities
。它基本上会使用授权的 username
、client_id
、scope
和 authorities
并执行相同的摘要算法在他们。这样,当 Bob 尝试登录时,他将获得相同的访问 token ,但底层 token 存储将识别他具有不同的身份验证(来自 token 授予者 bean 中的身份验证管理器)并刷新其数据库。这个解决方案的问题是它只依赖于底层 token 存储的实现行为(尽管 InMemoryTokenStore
和 JdbcTokenStore
都是这种方式)。
您能想到更好/更清洁的解决方案吗?我是不是想多了?
提前致谢。
最佳答案
我通过在发送身份验证信息时删除给定用户的所有 token 来解决我的应用程序中的这个问题。
使用自定义 AuthenticationProvider bean。
@Component("authenticationProvider")
public class AuthenticationProviderImpl implements AuthenticationProvider
在 token 存储 bean 中 Autowiring 。
@Autowired
@Qualifier("tokenStore")
private TokenStore tokenStore;
然后在身份验证方法中,如果凭据第二次通过,则删除给定用户的所有 token 。
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) authentication;
try {
//Do authentication
//Delete previous tokens
Collection<OAuth2AccessToken> tokenCollection = tokenStore.findTokensByUserName(token.getName());
for (OAuth2AccessToken oToken : tokenCollection){
tokenStore.removeAccessToken(oToken);
}
//return Authentication;
}
}
大多数请求将使用 token 并将完全绕过它,但是当凭据通过时,将生成一个新 token 。此 token 将与新的身份验证对象相关联,该对象将包括所有新角色以及对用户所做的更改。
关于java - 使用 Spring Security OAuth2,刷新 TokenStore 中存储的身份验证的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18261626/