java - 使用 Spring Security OAuth2,刷新 TokenStore 中存储的身份验证的正确方法是什么?

标签 java oauth spring-security

我们正在使用资源所有者凭据授权类型(在 security-config.xml 中使用 oauth2:password。让我们用这个场景来解释我的困境:

  1. Bob 的创建权限为 ROLE_USER
  2. Bob 尝试访问受 oauth2 保护的资源
  3. Bob 使用官方移动应用程序访问它,因此客户端凭据是正确的
  4. Bob 的访问 token 已创建并存储在 TokenStore 中,以他的 usernameclient_idscope 为关键字>。 (参见 DefaultAuthenticationKeyGenerator.java)
  5. Bob 的手机尝试使用此访问 token 调用 protected 服务,但这些服务要求用户拥有 ROLE_MOBILE_USER权限
  6. Bob 联系数据库所有者并将 ROLE_MOBLE_USER 添加到他在数据库中的用户。
  7. Bob 尝试获取另一个访问 token ,但 DefaultTokenServices 返回给他相同的、无效的访问 token 。
  8. 利用他的新权限的唯一方法是等到他的旧访问 token 过期,这样他就可以获得具有正确权限的新访问 token 。

有很多方法可以解决这个问题。

首先,将 ROLE_MOBILE_USER 添加到 Bob 权限的管理应用程序随后可以清除数据库中的所有访问 token 和授权。通过这种方式,DefaultTokenServices 将创建一个新的具有正确权限的序列化为他的新 OAuth2Authentication。然而,此时我们可能不希望 Administration webapp 关注 OAuth(至少现在不)。如果可能的话,我们希望管理应用程序的关注点尽可能简洁,并且现在不依赖于 oauth。

我们可以将 DELETE 方法暴露给 /oauth/access_token 端点,并告诉移动应用程序尝试删除该访问 token 并重新请求一个,以防万一存储的 authorities 是陈旧的。不过,这感觉更像是一种解决方法。

最后,我可以在我自己定义的 AuthenticationKeyGenerator 中序列化 authorities。它基本上会使用授权的 usernameclient_idscopeauthorities 并执行相同的摘要算法在他们。这样,当 Bob 尝试登录时,他将获得相同的访问 token ,但底层 token 存储将识别他具有不同的身份验证(来自 token 授​​予者 bean 中的身份验证管理器)并刷新其数据库。这个解决方案的问题是它只依赖于底层 token 存储的实现行为(尽管 InMemoryTokenStoreJdbcTokenStore 都是这种方式)。

您能想到更好/更清洁的解决方案吗?我是不是想多了?

提前致谢。

最佳答案

我通过在发送身份验证信息时删除给定用户的所有 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/

相关文章:

php - 使用 eBay OAuth

java - 如何下载 edu.mit.sketch.geom 库

java - 我应该在 throws 子句中抛出 Exception 的子类型吗?

java - 在JavaFX中静音一个WebView,有可能吗?

java - ZeroMQ,我们可以使用 inproc : transport along with pub/sub messaging pattern

oauth - 需要通过 oauth 插件对使用 Twitter、Google、Facebook API 的用户进行身份验证吗?

php - 如何生成 OAuth 签名

java - 为什么 hello world 在 Spring 中不显示并出现异常?

java - 没有类型为 'org.springframework.cloud.bootstrap.encrypt.RsaProperties' 的合格 bean

java - Spring Security 根据入参标准进行授权