我是新的是Oauth和Spring-Security。我尝试使用客户端详细信息和数据库中的令牌详细信息将oauth与Spring Security集成。我正在使用spring-security
和spring-security-oauth
的最新版权限。以下是我的依赖:
<!-- Spring Security Dependencies -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
</dependency>
<!-- END of Core Spring and Spring Web Dependencies -->
版本如下:
<spring-security-oauth2>2.0.1.RELEASE</spring-security-oauth2>
<spring.security.version>3.2.4.RELEASE</spring.security.version>
这是我的maven多模块项目。所以在父模块中管理所有依赖关系。
以下是我的spring-security-config.xml
oauth2。
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
xmlns:sec="http://www.springframework.org/schema/security" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-1.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd ">
<!-- Create client details bean for manage client details from database -->
<!-- The JdbcClientDetailsService provide default implementation for fetching
the data from oauth_client_details table Other wise we need to create our
custom class that Implement ClientDetailsService Interface and override its
loadClientByClientId method -->
<bean id="clientDetails"
class="org.springframework.security.oauth2.provider.client.JdbcClientDetailsService">
<constructor-arg index="0">
<ref bean="dataSource" />
</constructor-arg>
</bean>
<!-- Configure Authentication manager -->
<bean id="passwordEncoder"
class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
<constructor-arg name="strength" value="11" />
</bean>
<!-- This class is the custom implementation of UserDetailSerive Interface
that provide by the spring, which we Need to implement and override its method.
But for Oauth spring provide us ClientDetailsUserDetailsService, which already
implement UserDetailSerive Interface and override its method. -->
<bean id="clientDetailsUserService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="clientDetails" />
<property name="passwordEncoder" ref="passwordEncoder"></property>
</bean>
<!-- <bean id="oauthDaoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<property name="passwordEncoder" ref="passwordEncoder" /> <property name="userDetailsService"
ref="clientDetailsUserService" /> </bean> -->
<sec:authentication-manager id="oauthAuthenticationManager">
<sec:authentication-provider
user-service-ref="clientDetailsUserService" />
</sec:authentication-manager>
<!-- Oauth Token Service Using Database -->
<!-- The JdbcTokenStore class provide the default implementation from access
the token from database. If we want to customize the JDBC implementation
we need to implement TokenStore interface and overrider its methods -->
<bean id="tokenStore"
class="org.springframework.security.oauth2.provider.token.store.JdbcTokenStore">
<constructor-arg ref="dataSource" />
</bean>
<!-- This the service class which is used to access the function of JdbcTokenStore
class. This is like MVC structure JdbcTokenStore is Dao layer and DefaultTokenServices
is service layer -->
<bean id="tokenServices"
class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<property name="tokenStore" ref="tokenStore" />
<property name="supportRefreshToken" value="true" />
<property name="clientDetailsService" ref="clientDetails" />
</bean>
<!-- A user approval handler that remembers approval decisions by consulting
existing tokens -->
<bean id="oAuth2RequestFactory"
class="org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory">
<constructor-arg ref="clientDetails" />
</bean>
<bean id="userApprovalHandler"
class="org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler">
<property name="requestFactory" ref="oAuth2RequestFactory" />
<property name="tokenStore" ref="tokenStore" />
</bean>
<!-- Authorization Server Configuration of the server is used to provide
implementations of the client details service and token services and to enable
or disable certain aspects of the mechanism globally. -->
<oauth:authorization-server
client-details-service-ref="clientDetails" token-services-ref="tokenServices"
user-approval-handler-ref="userApprovalHandler">
<oauth:authorization-code />
<oauth:implicit />
<oauth:refresh-token />
<oauth:client-credentials />
<oauth:password />
</oauth:authorization-server>
-----------------------------
尝试部署应用程序时,下面的堆栈跟踪将启动控制台:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'oauth2TokenGranter': Cannot create inner bean '(inner bean)#1a0bdce' of type [org.springframework.security.oauth2.provider.password.ResourceOwnerPasswordTokenGranter] while setting constructor argument with key [4]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#1a0bdce': Cannot resolve reference to bean 'org.springframework.security.authenticationManager' while setting constructor argument; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'org.springframework.security.authenticationManager' is defined
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveInnerBean(BeanDefinitionValueResolver.java:290)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:129)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveManagedList(BeanDefinitionValueResolver.java:359)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:157)
at org.springframework.beans.factory.support.ConstructorResolver.resolveConstructorArguments(ConstructorResolver.java:632)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:140)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1114)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1017)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:703)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
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:4750)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5170)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1396)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1386)
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)
-------------------------------------
当我评论<oauth:authorization-server
配置文件中的spring-security-oauth.xml
配置时,没有错误,但是当我们取消注释时,异常将抛出。
答案 0 :(得分:4)
我找到了问题的解决方案,根据错误和spring-security api docs ResourceOwnerPasswordTokenGranter
类需要authenticationManager
来创建对象。所以只需替换:
<oauth:authorization-server
client-details-service-ref="clientDetails" token-services-ref="tokenServices"
user-approval-handler-ref="userApprovalHandler">
------------------
<oauth:password />
</oauth:authorization-server>
使用:
<oauth:authorization-server
client-details-service-ref="clientDetails" token-services-ref="tokenServices"
user-approval-handler-ref="userApprovalHandler">
------------------
<oauth:password authentication-manager-ref="authenticationManager"/>
</oauth:authorization-server>