Spring OAuth - 重新加载资源ID和身份验证权限

Posted

技术标签:

【中文标题】Spring OAuth - 重新加载资源ID和身份验证权限【英文标题】:Spring OAuth - Reload resourceIds and authorities of authentication 【发布时间】:2017-02-06 08:29:02 【问题描述】:

我只是应用了 Spring Boot 和 Spring Cloud 来构建一个微服务系统。我也对它应用了 Spring Oauth。老实说,一切都很完美。春天在这方面做得很好。 在这个系统中,我有一个微服务项目使用 JDBC 数据源完成 OAuth 服务器的工作,并且我使用基于权限的 UserDetails 权限(1 个用户有多个权限)。有几个微服务项目做资源服务器的工作(使用 Jersey 公开 Rest api),访问安全性基于 OAuth 持有者令牌的身份验证权限。

资源服务器 OAuth 配置类是这样的

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter 

   @Override
   public void configure(HttpSecurity http) throws Exception 

       http.sessionManagement()
           .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
       http.csrf().disable();

       http.authorizeRequests()                     
           .antMatchers("/restservice/object/list")
           .hasAuthority("PERMISSION_VIEW_OBJECT_LIST");

       //     ...
   

   @Override
   public void configure(ResourceServerSecurityConfigurer resources) 
              throws  Exception 
        resources.resourceId("abc-resource-id")
                 .tokenStore(new JdbcTokenStore(dataSource()));
   

   @Bean
   @ConfigurationProperties(prefix = "oauth2.datasource")
   public DataSource dataSource() 
       return DataSourceBuilder.create().build();
   

一切都很棒!但是我遇到了2个问题:

    如果我将新的微服务项目添加为新的 resourceId,并将 resourceId 值附加到 OAuth 客户端的表 OAUTH_CLIENT_DETAILS 中的 RESOURCE_IDS,则对新资源服务的 Rest API 的所有请求都会返回类似这样的错误 "error":"access_denied","error_description":"无效令牌不包含资源 id (xyz-resource-id)" 即使用户注销并重新登录以获取新的访问令牌,也会发生这种情况。仅当我去删除数据库中的访问令牌和刷新令牌 int 表 OAUTH_ACCESS_TOKEN 和 OAUTH_REFRESH_TOKEN 的记录时才有效。

    如果在运行时更改了用户的权限,但未重新加载身份验证权限,我看到表 OAUTH_ACCESS_TOKEN 中的访问令牌的 AUTHENTICATION 值仍然包含更改权限之前的旧权限。在这种情况下,用户必须注销并重新登录才能获得具有更改权限的新访问令牌。

那么,有什么方法可以解决这两个问题。 我正在使用 Spring Cloud Brixton.SR4 和 Spring Boot 1.3.5.RELEASE。

【问题讨论】:

【参考方案1】:

我通过这种方式解决了重新加载问题。

@Bean
public ClientDetailsService jdbcClientDetailsService() 
    return new JdbcClientDetailsService(dataSource);

【讨论】:

【参考方案2】:

如果您使用默认的 Spring JdbcTokenStore,那么当用户第一次进行身份验证并检索其令牌时,用户身份验证将被序列化并与访问/刷新令牌一起存储。

每次使用令牌进行身份验证时,都会加载此存储的身份验证,这就是为什么更改用户权限或添加额外资源不会反映在用户权限中的原因。

为了对此添加一些检查,您可以扩展 DefaultTokenServices 并覆盖 loadAuthentication(String accessTokenValue) 方法,以便在从令牌存储加载用户身份验证后执行您自己的检查。

这可能不是执行此操作的理想方式,但它是迄今为止我们发现的唯一方式。

要覆盖 DefaultTokenServices,请将以下 bean 方法添加到 AuthorizationServerConfigurerAdapter 配置类:

class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter 
    @Bean
    public AuthorizationServerTokenServices authorizationServerTokenServices() throws Exception 
        // Where YourTokenServices extends DefaultTokenServices
        YourTokenServices tokenServices = new YourTokenServices();
        tokenServices.setTokenStore(tokenStore);
        tokenServices.setClientDetailsService(clientDetailsService);
        return tokenServices;
    

【讨论】:

感谢您的帮助。您的意思是在资源服务器或 OAuth 服务器中扩展 DefaultTokenServices?对不起,我的愚蠢,我该如何配置注入自定义 TokenServices 类? 在身份验证服务器中,这是加载用户详细信息的部分。我已将实现添加到我的答案中 非常感谢,我试试看。

以上是关于Spring OAuth - 重新加载资源ID和身份验证权限的主要内容,如果未能解决你的问题,请参考以下文章

使用 Spring OAuth 支持多个资源 ID

Spring security oAuth 2.0(无效令牌不包含资源ID(oauth2-resource))

spring-oauth-server实践(2-1)问题澄清-关于资源角色和scope

Spring Security 自定义资源服务器实践

Spring Cloud微服务安全实战_4-5_搭建OAuth2资源服务器

Spring Security---Oauth2详解