2016-05-16 67 views
0

我想實現Oauth2彈簧安全與春天4.1 我發送密碼,用戶名,client_id和client_secret但仍然收到錯誤憑據。 我發送請求如下:Oauth2與春投丟壞的憑據

http://localhost:8080/asset-manager/oauth/token?grant_type=password&client_id=restapp&client_secret=restapp&username=ankita&password=ankita

我有以下文件

彈簧security.xml文件

<?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:context="http://www.springframework.org/schema/context" 
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.xsd 
    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd 
    http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.1.xsd 
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd 
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd "> 

<!-- This is default url to get a token from OAuth --> 
<http pattern="/oauth/token" create-session="stateless" 
    authentication-manager-ref="clientAuthenticationManager" 
    xmlns="http://www.springframework.org/schema/security"> 
    <intercept-url pattern="/oauth/token" access="isFullyAuthenticated()" /> 
    <anonymous enabled="false" /> 
    <http-basic entry-point-ref="clientAuthenticationEntryPoint" /> 
    <!-- include this only if you need to authenticate clients via request 
     parameters --> 
    <custom-filter ref="clientCredentialsTokenEndpointFilter" 
     after="BASIC_AUTH_FILTER" /> 
    <access-denied-handler ref="oauthAccessDeniedHandler" /> 
    <csrf disabled="true" /> 
</http> 

<!-- This is where we tells spring security what URL should be protected 
    and what roles have access to them --> 
<http pattern="/api/**" create-session="never" 
    entry-point-ref="oauthAuthenticationEntryPoint" 
    access-decision-manager-ref="accessDecisionManager" 
    xmlns="http://www.springframework.org/schema/security"> 
    <anonymous enabled="false" /> 
    <intercept-url pattern="/api/**" access="hasRole('ROLE_USER')" /> 
    <custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" /> 
    <access-denied-handler ref="oauthAccessDeniedHandler" /> 
    <csrf disabled="true" /> 
</http> 


<bean id="oauthAuthenticationEntryPoint" 
    class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint"> 
    <property name="realmName" value="test" /> 
</bean> 

<bean id="requestFactory" 
    class="org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory"> 
    <constructor-arg name="clientDetailsService" ref="clientDetails" /> 
</bean> 

<bean id="clientAuthenticationEntryPoint" 
    class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint"> 
    <property name="realmName" value="test/client" /> 
    <property name="typeName" value="Basic" /> 
</bean> 

<bean id="oauthAccessDeniedHandler" 
    class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" /> 

<bean id="clientCredentialsTokenEndpointFilter" 
    class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter"> 
    <property name="authenticationManager" ref="authenticationManager" /> 
</bean> 

<bean id="accessDecisionManager" 
    class="org.springframework.security.access.vote.AffirmativeBased" 
    xmlns="http://www.springframework.org/schema/beans"> 
    <constructor-arg> 
     <list> 
      <bean class="org.springframework.security.oauth2.provider.vote.ScopeVoter" /> 
      <bean class="org.springframework.security.access.vote.RoleVoter" /> 
      <bean class="org.springframework.security.access.vote.AuthenticatedVoter" /> 
      <bean 
       class="org.springframework.security.web.access.expression.WebExpressionVoter"></bean> 
     </list> 
    </constructor-arg> 
</bean> 


<authentication-manager id="clientAuthenticationManager" 
    xmlns="http://www.springframework.org/schema/security"> 
    <authentication-provider user-service-ref="clientDetailsUserService" /> 
</authentication-manager> 

<bean id="authenticationProcessingFilter" 
    class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter"> 
    <property name="authenticationManager" ref="authenticationManager" /> 
</bean> 
<!-- This is simple authentication manager, with a hardcoded user/password 
    combination. We can replace this with a user defined service to get few users 
    credentials from DB --> 
<authentication-manager alias="authenticationManager" 
    xmlns="http://www.springframework.org/schema/security"> 
    <authentication-provider> 
     <user-service> 
      <user name="ankita" password="ankita" authorities="ROLE_USER" /> 
     </user-service> 
    </authentication-provider> 
    <authentication-provider user-service-ref="clientDetailsUserService" /> 

</authentication-manager> 

<bean id="clientDetailsUserService" 
    class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService"> 
    <constructor-arg ref="clientDetails" /> 
</bean> 


<!-- This defined token store, we have used inmemory tokenstore for now 
    but this can be changed to a user defined one --> 
<bean id="tokenStore" 
    class="org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore" /> 

<!-- This is where we defined token based configurations, token validity 
    and other things --> 
<bean id="tokenServices" 
    class="org.springframework.security.oauth2.provider.token.DefaultTokenServices"> 
    <property name="tokenStore" ref="tokenStore" /> 
    <property name="supportRefreshToken" value="true" /> 
    <property name="accessTokenValiditySeconds" value="120" /> 
    <property name="clientDetailsService" ref="clientDetails" /> 
</bean> 

<bean id="userApprovalHandler" 
    class="org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler"> 
    <property name="tokenStore" ref="tokenStore" /> 
    <property name="clientDetailsService" ref="clientDetails" /> 
    <property name="requestFactory" ref="requestFactory" /> 
</bean> 

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

<oauth:resource-server id="resourceServerFilter" 
    resource-id="test" token-services-ref="tokenServices" /> 

<oauth:client-details-service id="clientDetails"> 
    <!-- client --> 
    <oauth:client client-id="restapp" 
     authorized-grant-types="authorization_code,client_credentials" 
     authorities="ROLE_USER" scope="read,write,trust" secret="secret" /> 

    <oauth:client client-id="restapp" 
     authorized-grant-types="password,authorization_code,refresh_token,implicit" 
     secret="restapp" scope="read,write,trust" authorities="ROLE_USER" /> 

</oauth:client-details-service> 
<bean id="httpSessionSecurityContextRepository" 
    class='org.springframework.security.web.context.HttpSessionSecurityContextRepository'> 
    <property name='allowSessionCreation' value='false' /> 
</bean> 
<bean id="securityContextPersistenceFilter" 
    class="org.springframework.security.web.context.SecurityContextPersistenceFilter"> 
    <constructor-arg ref="httpSessionSecurityContextRepository" /> 
</bean> 
<bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy"> 
    <constructor-arg> 
     <list> 
      <sec:filter-chain pattern="/**" 
       filters="securityContextPersistenceFilter" /> 
     </list> 
    </constructor-arg> 
</bean> 
<sec:global-method-security 
    pre-post-annotations="enabled" proxy-target-class="true" 
    authentication-manager-ref="authenticationManager" 
    secured-annotations="enabled"> 
    <!--you could also wire in the expression handler up at the layer of the 
     http filters. See https://jira.springsource.org/browse/SEC-1452 --> 
    <sec:expression-handler ref="oauthExpressionHandler" /> 
</sec:global-method-security> 

<oauth:expression-handler id="oauthExpressionHandler" /> 
<oauth:web-expression-handler id="oauthWebExpressionHandler" /> 

這是我的pom.xml

<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
version="2.5"> 



<servlet> 
    <servlet-name>mvc-dispatcher</servlet-name> 
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
    <load-on-startup>1</load-on-startup> 
</servlet> 

<servlet-mapping> 
    <servlet-name>mvc-dispatcher</servlet-name> 
    <url-pattern>/</url-pattern> 
</servlet-mapping> 
<context-param> 
    <param-name>contextConfigLocation</param-name> 
    <param-value> 
    /WEB-INF/mvc-dispatcher-servlet.xml,   
     /WEB-INF/spring-security.xml 
     </param-value> 
</context-param> 

<listener> 
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
</listener> 

<!-- Spring Security --> 

<filter> 
    <filter-name>springSecurityFilterChain</filter-name> 
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> 
</filter> 

<filter-mapping> 
    <filter-name>springSecurityFilterChain</filter-name> 
    <url-pattern>/*</url-pattern> 
</filter-mapping> 
<listener> 
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> 
</listener> 
<listener> 
    <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class> 
</listener> 

不幸的是,每當我發出請求時,它拋出這個:

{ 
    "error": "invalid_grant", 
    "error_description": "Bad credentials" 
} 

需要幫助!

回答

0

我不得不更改一些spring-security.xml文件中具有更新功能的屬性,並且我還根據我的用例覆蓋了一些類,如AuthenticationProvider和ClientDetailsS​​ervice,我還使用redis作爲我的令牌存儲,你可以將它替換成內存令牌存儲

我更新了spring-security。xml是:

<?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:context="http://www.springframework.org/schema/context" 
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.xsd 
    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd 
    http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.1.xsd 
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd 
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd "> 

<!-- This is default url to get a token from OAuth --> 
<http pattern="/oauth/token" create-session="stateless" 
    authentication-manager-ref="clientAuthenticationManager" 
    xmlns="http://www.springframework.org/schema/security"> 
    <intercept-url pattern="/oauth/token" access="isFullyAuthenticated()" method="POST"/> 
    <intercept-url pattern="/v1/access_token" access="isFullyAuthenticated()" method="POST"/> 
    <anonymous enabled="false" /> 
    <http-basic entry-point-ref="oauthAuthenticationEntryPoint" /> 
    <!-- include this only if you need to authenticate clients via request 
     userService parameters --> 
    <custom-filter ref="clientCredentialsTokenEndpointFilter" 
     after="BASIC_AUTH_FILTER" /> 
    <access-denied-handler ref="oauthAccessDeniedHandler" /> 
    <csrf disabled="true" /> 
</http> 

<!-- This is where we tells spring security what URL should be protected 
    and what roles have access to them --> 
<http pattern="/v1/**" create-session="stateless" 
    entry-point-ref="oauthAuthenticationEntryPoint" 
    access-decision-manager-ref="accessDecisionManager" 
    xmlns="http://www.springframework.org/schema/security"> 
    <anonymous enabled="false" /> 
    <intercept-url pattern="/v1/application/register" access="hasRole('ROLE_ADMIN')" /> 
    <intercept-url pattern="/v1/application/{clientId}" access="hasAnyRole('ROLE_USER','ROLE_ADMIN')" /> 
    <custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" /> 
    <access-denied-handler ref="oauthAccessDeniedHandler" /> 
    <csrf disabled="true" /> 
</http> 

<bean id="oauthAuthenticationEntryPoint" 
    class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint"> 
    <property name="realmName" value="test" /> 
</bean> 

<bean id="clientAuthenticationEntryPoint" 
    class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint"> 
    <property name="realmName" value="test/client" /> 
    <property name="typeName" value="Basic" /> 
</bean> 

<bean id="oauthAccessDeniedHandler" 
    class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" /> 

<bean id="clientCredentialsTokenEndpointFilter" 
    class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter"> 
    <property name="authenticationManager" ref="authenticationManager" /> 
</bean> 

<bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased" 
    xmlns="http://www.springframework.org/schema/beans"> 
    <constructor-arg> 
     <list> 
      <bean class="org.springframework.security.oauth2.provider.vote.ScopeVoter" /> 
      <bean class="org.springframework.security.access.vote.RoleVoter" /> 
      <bean class="org.springframework.security.access.vote.AuthenticatedVoter" /> 
      <bean 
       class="org.springframework.security.web.access.expression.WebExpressionVoter" /> 
     </list> 
    </constructor-arg> 
</bean> 

<authentication-manager id="clientAuthenticationManager" 
    xmlns="http://www.springframework.org/schema/security"> 
    <!-- <authentication-provider user-service-ref="clientDetailsUserService" 
     /> --> 
    <authentication-provider ref="AuthenticationProvider" /> 
</authentication-manager> 

<bean id="clientDetailsUserService" 
    class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService"> 
    <constructor-arg ref="clientDetailsService" /> 
</bean> 

<authentication-manager 
    xmlns="http://www.springframework.org/schema/security" alias="authenticationManager"> 
    <authentication-provider ref="AuthenticationProvider" /> 
</authentication-manager> 

<bean id="AuthenticationProvider" 
    class="com.timeinc.security.biz.client.security.impl.AuthenticationProviderImpl"> 
    <property name="userService" ref="userService"></property> 
</bean> 

<bean id="tokenStore" 
    class="org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore"> 
    <constructor-arg name="connectionFactory" ref="redisConnectionFactory" /> 
</bean> 

<!--create redis connection factory and set db 1 --> 
<bean id="redisConnectionFactory" 
    class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"> 
    <property name="hostName" value="${redisHost}" /> 
    <property name="port" value="${redisPort}" /> 
    <property name="password" value="${redisPassword}" /> 
    <property name="database" value="${redisDatabase}" /> 
</bean> 

<bean id="tokenServices" class="com.timeinc.security.biz.client.security.impl.DefaultTokenServicesImpl"> 
    <property name="tokenStore" ref="tokenStore" /> 
    <property name="supportRefreshToken" value="true" /> 
    <property name="accessTokenValiditySeconds" value="${accessTokenValiditySeconds}" /> 
    <property name="refreshTokenValiditySeconds" value="${refreshTokenValiditySeconds}"></property> 
    <property name="clientDetailsService" ref="clientDetailsService" /> 
</bean> 

<bean id="requestFactory" 
    class="org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory"> 
    <constructor-arg name="clientDetailsService" ref="clientDetailsService" /> 
</bean> 

<bean id="userApprovalHandler" 
    class="org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler"> 
    <property name="tokenStore" ref="tokenStore" /> 
    <property name="clientDetailsService" ref="clientDetailsService" /> 
    <property name="requestFactory" ref="requestFactory" /> 
</bean> 

<oauth:authorization-server 
    client-details-service-ref="clientDetailsService" 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> 

<oauth:resource-server id="resourceServerFilter" 
    resource-id="test" token-services-ref="tokenServices" /> 


<bean id="clientDetailsService" class="com.timeinc.security.biz.client.security.impl.ClientDetailsServiceImpl"> 
    <property name="appClient" ref="appClient"></property> 
</bean> 
<bean id="httpSessionSecurityContextRepository" 
    class='org.springframework.security.web.context.HttpSessionSecurityContextRepository'> 
    <property name='allowSessionCreation' value='false' /> 
</bean> 

<bean id="userService" class="com.timeinc.security.biz.client.security.impl.UserDetailsServiceImpl"> 
    <property name="appClient" ref="appClient"></property> 
</bean> 

<bean id="securityContextPersistenceFilter" 
    class="org.springframework.security.web.context.SecurityContextPersistenceFilter"> 
    <constructor-arg ref="httpSessionSecurityContextRepository" /> 
</bean> 
<bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy"> 
    <constructor-arg> 
     <list> 
      <sec:filter-chain pattern="/**" 
       filters="securityContextPersistenceFilter" /> 
     </list> 
    </constructor-arg> 
</bean> 
<sec:global-method-security 
    pre-post-annotations="enabled" proxy-target-class="true"> 
    <!--you could also wire in the expression handler up at the layer of the 
     http filters. See https://jira.springsource.org/browse/SEC-1452 --> 
    <sec:expression-handler ref="oauthExpressionHandler" /> 
</sec:global-method-security> 

<oauth:expression-handler id="oauthExpressionHandler" /> 
<oauth:web-expression-handler id="oauthWebExpressionHandler" /> 

</beans> 
+0

怎麼能有人知道哪個配置解決了你的問題? – Stephan

0

您只需要傳遞用戶名,密碼(這兩個都是用戶,而不是客戶端),grant_type和client_id請求參數。

您必須使用客戶端ID作爲用戶名和客戶端密碼作爲密碼發送授權標頭,其中包含BASIC身份驗證。

這是你會怎麼做,在捲曲例如:

$ curl -u restapp:restapp http://localhost:8080/asset-manager/oauth/token -d grant_type=password -d client_id=restapp 
0

我使用Spring Security 4.0.4升級到4.1.1時,也有類似的問題。

嘗試在你的認證管理器bean定義爲「ID」改變「別名」:

<authentication-manager id="authenticationManager" 
       xmlns="http://www.springframework.org/schema/security"> 
    <authentication-provider> 
     <user-service> 
      <user name="ankita" password="ankita" authorities="ROLE_USER" /> 
     </user-service> 
    </authentication-provider> 
<authentication-provider user-service-ref="clientDetailsUserService" /> 

我發現,由於某種原因,在自定義的「別名」定義「的AuthenticationManager」不沒有得到承認。當我將「別名」更改爲「id」時,我的自定義AuthenticationManager再次工作。

我在測試Spring Security 4.1.0時看到了這個問題,所以我不確定Spring Security 4.0.4和4.1.0之間的變化是什麼導致了這個問題的發生。

我試圖在Spring Security github中搜索發行說明和問題,但找不到與此相關的任何內容。我所知道的是,這個小修補程序爲我工作。

希望這會有所幫助。

+0

這並沒有解決我的問題,但你可以看看我發佈的答案 –

+0

感謝您的建議!我幫助了這些信息。因爲這個廢話我什麼也沒有工作,我真的不明白髮生了什麼事! – Eremite