具有Spring-Security的Oauth2:创建名为'oauth2TokenGranter'的bean时出错:无法创建ResourceOwnerPasswordTokenGranter类型的内部bean

时间:2014-07-23 13:42:22

标签: java exception spring-security oauth-2.0

我是新的是Oauth和Spring-Security。我尝试使用客户端详细信息和数据库中的令牌详细信息将oauth与Spring Security集成。我正在使用spring-securityspring-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配置时,没有错误,但是当我们取消注释时,异常将抛出。

1 个答案:

答案 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>