我正在尝试使用基于 java 的配置将 Oauth2.0 与 Spring Security 集成到 Web 应用程序中。但是当我尝试调整示例应用程序时,我会抛出如下异常:
SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.harmeetsingh13.config.Oauth2SpringSecurityConfig$OauthWebSecurityConfigureAdapter': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter com.harmeetsingh13.config.Oauth2SpringSecurityConfig$OauthWebSecurityConfigureAdapter.clientCredentialsTokenEndpointFilter; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'clientCredentialsTokenEndpointFilter' defined in class com.harmeetsingh13.config.Oauth2SpringSecurityConfig: Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter com.harmeetsingh13.config.Oauth2SpringSecurityConfig.clientCredentialsTokenEndpointFilter(org.springframework.security.authentication.AuthenticationManager)] threw exception; nested exception is java.lang.NoClassDefFoundError: org/springframework/security/authentication/InternalAuthenticationServiceException
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1204)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:538)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:229)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:725)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4749)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5175)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1408)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1398)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter com.harmeetsingh13.config.Oauth2SpringSecurityConfig$OauthWebSecurityConfigureAdapter.clientCredentialsTokenEndpointFilter; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'clientCredentialsTokenEndpointFilter' defined in class com.harmeetsingh13.config.Oauth2SpringSecurityConfig: Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter com.harmeetsingh13.config.Oauth2SpringSecurityConfig.clientCredentialsTokenEndpointFilter(org.springframework.security.authentication.AuthenticationManager)] threw exception; nested exception is java.lang.NoClassDefFoundError: org/springframework/security/authentication/InternalAuthenticationServiceException
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:555)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperty
以下是我的 Spring 数据,基于 Java 的配置代码:
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages={"com.harmeetsingh13.repo"})
@PropertySource(value="classpath:properties/db.properties")
public class SpringDataConfig {
@Autowired
private Environment environment;
@Bean
public DataSource dataSource() {
try{
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setJdbcUrl(environment.getProperty("db.url"));
dataSource.setDriverClass(environment.getProperty("db.driver.class"));
dataSource.setUser(environment.getProperty("db.username"));
dataSource.setPassword(environment.getProperty("db.password"));
dataSource.setAcquireIncrement(5);
dataSource.setIdleConnectionTestPeriod(60);
dataSource.setMaxPoolSize(100);
dataSource.setMaxStatements(50);
dataSource.setMinPoolSize(10);
return dataSource;
}catch(Exception ex){
throw new RuntimeException(ex);
}
}
private JpaVendorAdapter jpaVendorAdapter() {
HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
jpaVendorAdapter.setShowSql(true);
jpaVendorAdapter.setDatabase(Database.MYSQL);
return jpaVendorAdapter;
}
@Bean
@Autowired
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(dataSource);
factoryBean.setPackagesToScan(environment.getProperty("package.scan"));
factoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);
factoryBean.setJpaVendorAdapter(jpaVendorAdapter());
return factoryBean;
}
@Bean
@Autowired
public JpaTransactionManager transactionManager(LocalContainerEntityManagerFactoryBean factoryBean) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(factoryBean.getObject());
return transactionManager;
}
}
以下是我的 Oauth2.0 集成代码:
@Configuration
@EnableWebMvcSecurity
@EnableAuthorizationServer
public class Oauth2SpringSecurityConfig extends AuthorizationServerConfigurerAdapter{
@Autowired
private DataSource dataSource;
@Bean
@Autowired
public ClientDetailsService clientDetailService() {
return new JdbcClientDetailsService(dataSource);
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(11);
}
@Bean
@Autowired
public UserDetailsService userDetailService(ClientDetailsService clientDetailsService) {
return new ClientDetailsUserDetailsService(clientDetailsService);
}
@Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}
@Bean
@Autowired
public DefaultTokenServices tokenService(TokenStore tokenStore, ClientDetailsService clientDetailsService) {
DefaultTokenServices tokenServices = new DefaultTokenServices();
tokenServices.setTokenStore(tokenStore);
tokenServices.setClientDetailsService(clientDetailsService);
return tokenServices;
}
@Bean
@Autowired
public DefaultOAuth2RequestFactory oAuth2RequestFactory(ClientDetailsService clientDetailsService) {
DefaultOAuth2RequestFactory requestFactory = new DefaultOAuth2RequestFactory(clientDetailsService);
return requestFactory;
}
@Bean
@Autowired
public TokenStoreUserApprovalHandler userApprovalHandler(DefaultOAuth2RequestFactory requestFactory, TokenStore tokenStore) {
TokenStoreUserApprovalHandler userApprovalHandler = new TokenStoreUserApprovalHandler();
userApprovalHandler.setRequestFactory(requestFactory);
userApprovalHandler.setTokenStore(tokenStore);
return userApprovalHandler;
}
@Bean(name="clientAuthenticationEntryPoint")
public OAuth2AuthenticationEntryPoint clientAuthenticationEntryPoint() {
OAuth2AuthenticationEntryPoint entryPoint = new OAuth2AuthenticationEntryPoint();
entryPoint.setRealmName("Authorization/client");
entryPoint.setTypeName("Basic");
return entryPoint;
}
@Bean(name="oauthAuthenticationEntryPoint")
public OAuth2AuthenticationEntryPoint oauthAuthenticationEntryPoint() {
OAuth2AuthenticationEntryPoint entryPoint = new OAuth2AuthenticationEntryPoint();
entryPoint.setRealmName("Authorization");
return entryPoint;
}
@Bean
public OAuth2AccessDeniedHandler oauthAccessDeniedHandler() {
OAuth2AccessDeniedHandler accessDeniedHandler = new OAuth2AccessDeniedHandler();
return accessDeniedHandler;
}
@Bean
@Autowired
public AuthenticationManager getAuthenticationManager(ClientDetailsService clientDetailsService,DefaultTokenServices tokenServices) {
OAuth2AuthenticationManager authenticationManager = new OAuth2AuthenticationManager();
authenticationManager.setClientDetailsService(clientDetailsService);
authenticationManager.setTokenServices(tokenServices);
return authenticationManager;
}
//Oauth Have different ways for check user credentials like client_cridentials, password etc. This is for client_cridentials
@Bean
@Autowired
public ClientCredentialsTokenEndpointFilter clientCredentialsTokenEndpointFilter(AuthenticationManager authenticationManager) {
ClientCredentialsTokenEndpointFilter accessTokenProvider = new ClientCredentialsTokenEndpointFilter();
accessTokenProvider.setAuthenticationManager(authenticationManager);
return accessTokenProvider;
}
@Bean
public OAuth2ProtectedResourceDetails protectedResources() {
OAuth2ProtectedResourceDetails protectedResourceDetails = new ClientCredentialsResourceDetails();
return protectedResourceDetails;
}
@Configuration
@EnableAuthorizationServer
public static class AutorizationEndPoints extends AuthorizationServerConfigurerAdapter{
@Autowired
private ClientDetailsService clientDetailService;
@Autowired
private DefaultOAuth2RequestFactory requestFactory;
@Autowired
private UserApprovalHandler userApprovalHandler;
@Autowired
private DefaultTokenServices tokenService;
@Autowired
private AuthenticationManager authenticationManager;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endPoints)
throws Exception {
endPoints.clientDetailsService(clientDetailService);
endPoints.requestFactory(requestFactory);
endPoints.userApprovalHandler(userApprovalHandler);
endPoints.tokenServices(tokenService);
endPoints.authenticationManager(authenticationManager);
}
}
@Configuration
@EnableResourceServer
public static class ResurceServerConfig extends ResourceServerConfigurerAdapter{
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private DefaultTokenServices tokenServices;
@Autowired
private OAuth2AuthenticationEntryPoint oauthAuthenticationEntryPoint;
@Autowired
private OAuth2AccessDeniedHandler oauthAccessDeniedHandler;
@Override
public void configure(ResourceServerSecurityConfigurer resources)
throws Exception {
resources.resourceId("rsourceId");
resources.tokenServices(tokenServices);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.userDetailsService(userDetailsService)
.anonymous().disable()
.authorizeRequests()
.antMatchers("/api/**", "/user/**").hasRole("USER")
.antMatchers("/admin/**").hasRole("ADMIN")
.and()
.httpBasic()
.authenticationEntryPoint(oauthAuthenticationEntryPoint)
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.exceptionHandling().accessDeniedHandler(oauthAccessDeniedHandler);
}
}
@Order(1)
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public static class WebSecurityConfig extends WebSecurityConfigurerAdapter{
@Autowired
private UserDetailsService userDetailsService;
/*@Override
@Bean(name = "authenticationManager")
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}*/
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.userDetailsService(userDetailsService);
}
}
@Order(2)
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public static class OauthWebSecurityConfigureAdapter extends WebSecurityConfigurerAdapter{
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private OAuth2AuthenticationEntryPoint clientAuthenticationEntryPoint;
@Autowired
private ClientCredentialsTokenEndpointFilter clientCredentialsTokenEndpointFilter;
@Autowired
private OAuth2AccessDeniedHandler oauthAccessDeniedHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.userDetailsService(userDetailsService)
.anonymous().disable()
.authorizeRequests()
.antMatchers("/oauth/token")
.fullyAuthenticated()
.and()
.httpBasic()
.authenticationEntryPoint(clientAuthenticationEntryPoint)
.and()
.addFilterBefore(clientCredentialsTokenEndpointFilter, BasicAuthenticationFilter.class)
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.exceptionHandling().accessDeniedHandler(oauthAccessDeniedHandler);
}
}
@Order(3)
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public static class WebApplicationSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.formLogin()
.loginPage("/login")
.failureUrl("/login?login=error")
.defaultSuccessUrl("/successHandler")
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/login");
}
}
@Order(4)
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public static class AssetsSecurityConfig extends WebSecurityConfigurerAdapter{
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers("/assets/**");
}
}
}
提前感谢您的解决方案。我陷入了这个问题。