我有下面的安全配置类(在底部),最近已升级到;
我开始看到此错误消息,现在我的所有集成测试都失败并出现相同的错误;
引起:org.springframework.beans.factory.BeanCreationException: 创建名称为' securityConfig':注入自动装配的bean时出错 依赖失败;嵌套异常是 org.springframework.beans.factory.BeanCreationException:不能 autowire字段:私有 org.springframework.security.oauth2.provider.ClientDetailsService com.xyz.package.config.SecurityConfig.clientDetailsService;嵌套 例外是 org.springframework.beans.factory.BeanCurrentlyInCreationException: 创建名称为' clientDetailsService':请求bean的bean时出错 目前正在创作:是否存在无法解决的循环引用?
..............
..............
引起: org.springframework.beans.factory.BeanCurrentlyInCreationException: 创建名称为' clientDetailsService':请求bean的bean时出错 目前正在创作:是否存在无法解决的循环引用?
这肯定是由升级到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)中工作的东西不再起作用了。参见项目自述文件。