当前位置: 首页 > 知识库问答 >
问题:

Spring security OAuth2“ClientDetailsService”循环引用?

李昌勋
2023-03-14

我有以下安全配置类(在底部),最近升级到;

  • Spring Security(3.2.6.release)
  • Spring Security OAuth2(2.0.6.从2.0.3.发行版开始发行)

原因:org.springframework.beans.factory.BeanCurrentlyIncreationException:创建名为“Client DetailsService”的bean时出错:请求的bean当前正在创建中:是否存在不可html" target="_blank">解析的循环引用?

这肯定是升级到Spring Security OAuth2(2.0.6.release)造成的,我在2.0.3.release上没有这个。如果有人能给我一个关于这个问题的见解,我很感激。

提前道谢。

@Configuration 
public class SecurityConfig {

@Autowired
private DataSource dataSource;

@Autowired
private ClientDetailsService clientDetailsService;

@Autowired
private RedisConnectionFactory redisConnectionFactory;

@Bean
public TokenStore tokenStore() {
    return new PipelinedRedisTokenStore(redisConnectionFactory);
}

@Bean
public DefaultTokenServices tokenServices() throws Exception {
    DefaultTokenServices tokenServices = new DefaultTokenServices();
    tokenServices.setAccessTokenValiditySeconds(6000);
    tokenServices.setClientDetailsService(clientDetailsService);
    tokenServices.setTokenEnhancer(new MyTokenEnhancer());
    tokenServices.setSupportRefreshToken(true);
    tokenServices.setTokenStore(tokenStore());
    return tokenServices;
}

@Bean
public UserApprovalHandler userApprovalHandler() throws Exception {
    UserApprovalHandler handler = new MyUserApprovalHandler();
    handler.setApprovalStore(approvalStore());
    handler.setClientDetailsService(clientDetailsService);
    handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService));
    handler.setUseApprovalStore(true);
    return handler;
}

@Bean
public ApprovalStore approvalStore() {
    TokenApprovalStore store = new TokenApprovalStore();
    store.setTokenStore(tokenStore());
    return store;
}

@Bean
public OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler() {
    return new OAuth2AccessDeniedHandler();
}

@Configuration
@Priority(2000)
@EnableWebSecurity
protected static class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Value("${baseUrl}") 
    private String baseUrl;

    @Autowired
    private DataSource dataSource;
    
    @Resource
    private PasswordEncoder passwordEncoder;

    @Autowired
    private OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler;

    @Bean
    public ClientDetailsService clientDetailsService() throws Exception {
        ClientDetailsServiceConfiguration serviceConfig = new ClientDetailsServiceConfiguration();
            
        serviceConfig.clientDetailsServiceConfigurer().inMemory()
            .withClient("xxxx")
            .secret("some-secret")
            .authorizedGrantTypes("password", "authorization_code", "refresh_token", "client_credentials")
            .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
            .scopes("play", "trust");

        return serviceConfig.clientDetailsService();
    }
    
    @Bean
    UserDetailsService clientDetailsUserDetailsService() throws Exception {
        return new ClientDetailsUserDetailsService(clientDetailsService());
    }
    
    @Bean
    public ClientCredentialsTokenEndpointFilter clientCredentialsTokenEndpointFilter() throws Exception {
        ClientCredentialsTokenEndpointFilter filter = new ClientCredentialsTokenEndpointFilter();
        filter.setAuthenticationManager(authenticationManagerBean());
        filter.afterPropertiesSet();
        return filter;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        
        JdbcUserDetailsManagerConfigurer<AuthenticationManagerBuilder> jdbcUserDetail = new JdbcUserDetailsManagerConfigurer<AuthenticationManagerBuilder>();
        jdbcUserDetail.dataSource(dataSource);
        jdbcUserDetail.passwordEncoder(passwordEncoder);
        jdbcUserDetail.authoritiesByUsernameQuery("select a.username, r.role_name from account a, role r, account_role ar where a.id = ar.account_id and r.id = ar.role_id and a.username = ?");
        jdbcUserDetail.usersByUsernameQuery("select a.username, a.password, a.enabled, a.email from account a where a.username = ?");
        auth.apply(jdbcUserDetail);
        
        auth.userDetailsService(clientDetailsUserDetailsService());
        

    }
    
    @Bean(name="authenticationManager")
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
    
    @Bean
    protected AuthenticationEntryPoint authenticationEntryPoint() {
        OAuth2AuthenticationEntryPoint entryPoint = new OAuth2AuthenticationEntryPoint();
        entryPoint.setTypeName("Basic");
        entryPoint.setRealmName("realm/client");
        return entryPoint;
    }
    
    @Override
    public void configure(WebSecurity webSecurity) throws Exception {
        webSecurity
            .ignoring()
            .antMatchers("/resources/**", "/swagger/**", "/copyright*", "/api-docs/**")
            .antMatchers(HttpMethod.POST, "/api/**/account")
        .and()
            .debug(false);
    }
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        
        // @formatter:off
        http
            .anonymous().disable()
            .requiresChannel().anyRequest().requiresSecure();

        http
            .antMatcher("/oauth/token")
            .authorizeRequests().anyRequest().authenticated()
        .and()
            .httpBasic().authenticationEntryPoint(authenticationEntryPoint())
        .and()
            .csrf().requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/token")).disable()
            .exceptionHandling().accessDeniedHandler(oAuth2AccessDeniedHandler)
        .and()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        http
            .addFilterBefore(clientCredentialsTokenEndpointFilter(), BasicAuthenticationFilter.class);
        // @formatter:on

    }
    
}

@Configuration
@EnableResourceServer
protected static class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    
    @Autowired
    private ResourceServerTokenServices tokenServices;
    
    @Autowired
    private OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler;
    
    @Autowired
    ClientCredentialsTokenEndpointFilter clientCredentialsTokenEndpointFilter;
    
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        //resources.tokenServices(tokenServices);
        resources.resourceId("resource");
    }
    
    @Override
    public void configure(HttpSecurity http) throws Exception {

        // @formatter:off
        http
            .requiresChannel().anyRequest().requiresSecure();

        // API calls
        http
            .anonymous().disable()
            .authorizeRequests()
            .antMatchers("/api/**")
            .access("#oauth2.hasScope('trust') and #oauth2.hasScope('play') and (hasRole('ROLE_USER'))")
        .and()
            .addFilterBefore(clientCredentialsTokenEndpointFilter, BasicAuthenticationFilter.class)
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.NEVER)
        .and()
            .exceptionHandling()
            .accessDeniedHandler(oAuth2AccessDeniedHandler);
            
        // @formatter:on
    }
    
}

@Configuration
@EnableAuthorizationServer
protected static class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
    
    @Autowired
    private DataSource dataSource;
    
    @Autowired
    private AuthorizationServerTokenServices tokenServices;
    
    @Autowired
    private ClientDetailsService clientDetailsService;

    @Autowired
    private UserApprovalHandler userApprovalHandler;
    
    @Autowired
    private AuthenticationManager authenticationManager;
    
    @Autowired
    AuthenticationEntryPoint authenticationEntryPoint;

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints
        .tokenServices(tokenServices)
        .userApprovalHandler(userApprovalHandler)
        .authenticationManager(authenticationManager);
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients)
            throws Exception {
        clients.withClientDetails(clientDetailsService);
    }
    
    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer)
            throws Exception {
        oauthServer.authenticationEntryPoint(authenticationEntryPoint)
                .realm("realm/clients");
    }
    
}

}

**更新(3/17)**

为这个问题创建了https://github.com/aug70/security-sample。如果不改变配置,在以前的版本(2.0.3)中工作的东西似乎不再工作了。请参阅项目自述文件。

共有1个答案

公孙茂学
2023-03-14

解决方案张贴在此。使用Spring Security Oauth 2.0.9版本。

 类似资料:
  • 我有下面的安全配置类(在底部),最近升级到; Spring安全(3.2.6.释放) 我开始看到这些错误信息,现在我所有的集成测试都以同样的错误失败; 原因:org。springframework。豆。工厂BeanCreationException:创建名为“securityConfig”的bean时出错:自动连线依赖项的注入失败;嵌套的异常是org。springframework。豆。工厂Bean

  • 问题内容: 在正在进行的项目中,人们编写了服务类来访问DAO。几乎每个业务对象都具有使用自己的DAO的自己的服务。在某些服务上,我们使用对其他服务的引用。目前,人们正在实例化构造函数内部所需的服务。 但是现在,我遇到了麻烦,因为服务A需要服务B而服务B需要服务A,因此对任一构造函数的调用都会导致堆栈溢出… 示例(伪代码): 您将如何解决?使用单例模式? 谢谢 问题答案: Spring框架通过使用依

  • 一个实用的垃圾收集器大体上应该满足以下条件 一、消除悬空指针和内存泄露 二、不能给程序运行带来过高的额外开销,一般来说要控制在10% 三、尽量减少停顿时间,使得运行平稳 四、内存管理方面局部性尽量好 其中第一条没什么好说的,肯定要符合,至于第四条,当然也很重要,局部性做好了可以成倍提高运行速度,不过,如果都是内存操作,就算没做好速度一般也可以接受了,在老式的系统中,由于会用磁盘等外部存储扩展内存,

  • 问题内容: 给定一个以复杂的,循环的方式相互引用的类实例的集合:垃圾收集器是否可能无法释放这些对象? 我隐约记得过去这是JVM中的问题,但我 认为 这在几年前已解决。但是,在jhat中进行的一些调查显示,循环引用是我现在面临的内存泄漏的原因。 注意:我一直给人以JVM能够解析循环引用并从内存中释放这种“垃圾岛”的印象。 但是,我提出这个问题只是为了看看是否有人发现了任何异常。 问题答案: 循环引用

  • 本文向大家介绍C++中的循环引用,包括了C++中的循环引用的使用技巧和注意事项,需要的朋友参考一下 虽然C++11引入了智能指针的,但是开发人员在与内存的斗争问题上并没有解放,如果我门实用不当仍然有内存泄漏问题,其中智能指针的循环引用缺陷是最大的问题。 我们可以看到在出main函数作用域之前两个指针指向的内存并没有释放(指针指向的对象没有调用析构函数),我门把当前的引用数打印出来为2这个没有问题,

  • 我有圆形参考的问题。 我有Rest Webservices,它会将对象返回到前端,问题是当我试图返回具有多个引用的对象时,结果会得到无限的响应,从而生成 这些对象是由Hibernate代码生成自动生成的,我需要在后端有循环引用,我只需要在使用Jackson将信息发送到前端之前删除它。 控制器方法标头为: 我没有做任何明确的事情来转换为杰克逊,我是一个新手,我认为杰克逊自动解决了这个问题。