2014-03-26 84 views
3

我想實現一個簡單的客戶端憑據流spring-security-oauth2 api。我試圖去適應sparklr和tonr的例子,但沒有成功。我也試着按照這個線程的代碼:Spring-security context setup for 2-legged (client credentials) OAuth2 server,但它似乎並沒有與我合作。 有人可以給我看一個例子,或者幫助我解決這個問題。春季安全oauth 2和客戶端憑據流

爲spring-servlet.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: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-3.1.xsd 
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"> 

    <!-- Just for testing... --> 
    <http pattern="/oauth/cache_approvals" security="none" xmlns="http://www.springframework.org/schema/security" /> 
    <http pattern="/oauth/uncache_approvals" security="none" xmlns="http://www.springframework.org/schema/security" /> 

    <http pattern="/oauth/token" create-session="stateless" authentication-manager-ref="clientAuthenticationManager" 
      xmlns="http://www.springframework.org/schema/security"> 
     <intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" /> 
     <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" before="BASIC_AUTH_FILTER" /> 
     <access-denied-handler ref="oauthAccessDeniedHandler" /> 
    </http> 

    <!-- The OAuth2 protected resources are separated out into their own block so we can deal with authorization and error handling 
     separately. This isn't mandatory, but it makes it easier to control the behaviour. --> 
    <http pattern="/oauth/(users|clients)/.*" request-matcher="regex" create-session="stateless" entry-point-ref="oauthAuthenticationEntryPoint" 
      use-expressions="true" xmlns="http://www.springframework.org/schema/security"> 
     <anonymous enabled="false" /> 
     <intercept-url pattern="/oauth/users/([^/].*?)/tokens/.*" 
       access="#oauth2.clientHasRole('ROLE_CLIENT') and (hasRole('ROLE_USER') or #oauth2.isClient()) and #oauth2.hasScope('write')" 
       method="DELETE" /> 
     <intercept-url pattern="/oauth/users/.*" 
       access="#oauth2.clientHasRole('ROLE_CLIENT') and (hasRole('ROLE_USER') or #oauth2.isClient()) and #oauth2.hasScope('read')" 
       method="GET" /> 
     <intercept-url pattern="/oauth/clients/.*" 
       access="#oauth2.clientHasRole('ROLE_CLIENT') and #oauth2.isClient() and #oauth2.hasScope('read')" method="GET" /> 
     <intercept-url pattern="/**" access="denyAll()"/> 
     <custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" /> 
     <access-denied-handler ref="oauthAccessDeniedHandler" /> 
     <expression-handler ref="oauthWebExpressionHandler" /> 
    </http> 

    <!-- The OAuth2 protected resources are separated out into their own block so we can deal with authorization and error handling 
     separately. This isn't mandatory, but it makes it easier to control the behaviour. --> 
    <http pattern="/photos/**" 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="/photos" access="ROLE_USER,SCOPE_READ" /> 
     <intercept-url pattern="/photos/trusted/**" access="ROLE_CLIENT,SCOPE_TRUST" /> 
     <intercept-url pattern="/photos/user/**" access="ROLE_USER,SCOPE_TRUST" /> 
     <intercept-url pattern="/photos/**" access="ROLE_USER,SCOPE_READ" /> 
     <custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" /> 
     <access-denied-handler ref="oauthAccessDeniedHandler" /> 
    </http> 

    <!-- The OAuth2 protected resources are separated out into their own block so we can deal with authorization and error handling 
     separately. This isn't mandatory, but it makes it easier to control the behaviour. --> 
    <http pattern="/me/**" 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="/me" access="ROLE_USER,SCOPE_READ" /> 
     <custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" /> 
     <access-denied-handler ref="oauthAccessDeniedHandler" /> 
    </http> 

    <http access-denied-page="/login.jsp?authorization_error=true" disable-url-rewriting="true" 
      xmlns="http://www.springframework.org/schema/security"> 
     <intercept-url pattern="/oauth/**" access="ROLE_USER" /> 
     <intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" /> 

     <form-login authentication-failure-url="/login.jsp?authentication_error=true" default-target-url="/index.jsp" 
       login-page="/login.jsp" login-processing-url="/login.do" /> 
     <logout logout-success-url="/index.jsp" logout-url="/logout.do" /> 
     <anonymous /> 
    </http> 

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

    <bean id="clientAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint"> 
     <property name="realmName" value="sparklr2/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="clientAuthenticationManager" /> 
    </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" /> 
      </list> 
     </constructor-arg> 
    </bean> 

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

    <authentication-manager alias="authenticationManager" xmlns="http://www.springframework.org/schema/security"> 
     <authentication-provider> 
      <user-service id="userDetailsService"> 
       <user name="marissa" password="koala" authorities="ROLE_USER" /> 
       <user name="paul" password="emu" authorities="ROLE_USER" /> 
      </user-service> 
     </authentication-provider> 
    </authentication-manager> 

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

    <bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.InMemoryTokenStore" /> 

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

    <bean id="userApprovalHandler" class="org.springframework.security.oauth.examples.sparklr.oauth.SparklrUserApprovalHandler"> 
     <property name="autoApproveClients"> 
      <set> 
       <value>my-less-trusted-autoapprove-client</value> 
      </set> 
     </property> 
     <property name="tokenServices" ref="tokenServices" /> 
    </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="sparklr" token-services-ref="tokenServices" /> 

    <oauth:client-details-service id="clientDetails"> 
     <oauth:client client-id="my-trusted-client" authorized-grant-types="password,authorization_code,refresh_token,implicit" 
       authorities="ROLE_CLIENT, ROLE_TRUSTED_CLIENT" scope="read,write,trust" access-token-validity="60" /> 
     <oauth:client client-id="my-trusted-client-with-secret" authorized-grant-types="password,authorization_code,refresh_token,implicit" 
       secret="somesecret" authorities="ROLE_CLIENT, ROLE_TRUSTED_CLIENT" /> 
     <oauth:client client-id="my-client-with-secret" authorized-grant-types="client_credentials" authorities="ROLE_CLIENT" 
       scope="read" secret="secret" /> 
     <oauth:client client-id="my-less-trusted-client" authorized-grant-types="authorization_code,implicit" 
       authorities="ROLE_CLIENT" /> 
     <oauth:client client-id="my-less-trusted-autoapprove-client" authorized-grant-types="implicit" 
       authorities="ROLE_CLIENT" /> 
     <oauth:client client-id="my-client-with-registered-redirect" authorized-grant-types="authorization_code,client_credentials" 
       authorities="ROLE_CLIENT" redirect-uri="http://anywhere?key=value" scope="read,trust" /> 
     <oauth:client client-id="my-untrusted-client-with-registered-redirect" authorized-grant-types="authorization_code" 
       authorities="ROLE_CLIENT" redirect-uri="http://anywhere" scope="read" /> 
     <oauth:client client-id="tonr" resource-ids="sparklr" authorized-grant-types="client_credentials" 
       authorities="ROLE_CLIENT" scope="read,write" secret="secret" /> 
    </oauth:client-details-service> 

    <mvc:annotation-driven /> 

    <mvc:default-servlet-handler /> 

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

    <!--Basic application beans. --> 
    <bean id="viewResolver" class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"> 
     <property name="mediaTypes"> 
      <map> 
       <entry key="json" value="application/json" /> 
      </map> 
     </property> 
     <property name="viewResolvers"> 
      <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 
       <property name="prefix" value="/WEB-INF/jsp/"></property> 
       <property name="suffix" value=".jsp"></property> 
      </bean> 
     </property> 
     <property name="defaultViews"> 
      <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"> 
       <property name="extractValueFromSingleKeyModel" value="true" /> 
      </bean> 
     </property> 
    </bean> 

    <bean id="photoController" class="org.springframework.security.oauth.examples.sparklr.mvc.PhotoController"> 
     <property name="photoService" ref="photoServices" /> 
    </bean> 

    <bean id="photoServiceUserController" class="org.springframework.security.oauth.examples.sparklr.mvc.PhotoServiceUserController"> 
     <property name="userDetailsService" ref="userDetailsService" /> 
    </bean> 

    <bean id="adminController" class="org.springframework.security.oauth.examples.sparklr.mvc.AdminController"> 
     <property name="tokenServices" ref="tokenServices" /> 
     <property name="userApprovalHandler" ref="userApprovalHandler" /> 
    </bean> 

    <!-- Override the default mappings for approval and error pages --> 
    <bean id="accessConfirmationController" class="org.springframework.security.oauth.examples.sparklr.mvc.AccessConfirmationController"> 
     <property name="clientDetailsService" ref="clientDetails" /> 
    </bean> 

    <bean id="photoServices" class="org.springframework.security.oauth.examples.sparklr.impl.PhotoServiceImpl"> 
     <property name="photos"> 
      <list> 
       <bean class="org.springframework.security.oauth.examples.sparklr.PhotoInfo"> 
        <property name="id" value="1" /> 
        <property name="name" value="photo1.jpg" /> 
        <property name="userId" value="marissa" /> 
        <property name="resourceURL" value="/org/springframework/security/oauth/examples/sparklr/impl/resources/photo1.jpg" /> 
       </bean> 
       <bean class="org.springframework.security.oauth.examples.sparklr.PhotoInfo"> 
        <property name="id" value="2" /> 
        <property name="name" value="photo2.jpg" /> 
        <property name="userId" value="paul" /> 
        <property name="resourceURL" value="/org/springframework/security/oauth/examples/sparklr/impl/resources/photo2.jpg" /> 
       </bean> 
       <bean class="org.springframework.security.oauth.examples.sparklr.PhotoInfo"> 
        <property name="id" value="3" /> 
        <property name="name" value="photo3.jpg" /> 
        <property name="userId" value="marissa" /> 
        <property name="resourceURL" value="/org/springframework/security/oauth/examples/sparklr/impl/resources/photo3.jpg" /> 
       </bean> 
       <bean class="org.springframework.security.oauth.examples.sparklr.PhotoInfo"> 
        <property name="id" value="4" /> 
        <property name="name" value="photo4.jpg" /> 
        <property name="userId" value="paul" /> 
        <property name="resourceURL" value="/org/springframework/security/oauth/examples/sparklr/impl/resources/photo4.jpg" /> 
       </bean> 
       <bean class="org.springframework.security.oauth.examples.sparklr.PhotoInfo"> 
        <property name="id" value="5" /> 
        <property name="name" value="photo5.jpg" /> 
        <property name="userId" value="marissa" /> 
        <property name="resourceURL" value="/org/springframework/security/oauth/examples/sparklr/impl/resources/photo5.jpg" /> 
       </bean> 
       <bean class="org.springframework.security.oauth.examples.sparklr.PhotoInfo"> 
        <property name="id" value="6" /> 
        <property name="name" value="photo6.jpg" /> 
        <property name="userId" value="paul" /> 
        <property name="resourceURL" value="/org/springframework/security/oauth/examples/sparklr/impl/resources/photo6.jpg" /> 
       </bean> 
      </list> 
     </property> 
    </bean> 

</beans> 

爲spring-servlet.xml在TONR應用sparklr應用

<?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:mvc="http://www.springframework.org/schema/mvc" xmlns:sec="http://www.springframework.org/schema/security" 
     xmlns:oauth="http://www.springframework.org/schema/security/oauth2" xmlns:context="http://www.springframework.org/schema/context" 
     xmlns:aop="http://www.springframework.org/schema/aop" 
     xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd 
    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-3.1.xsd 
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd"> 

    <http access-denied-page="/login.jsp?authorization_error=true" xmlns="http://www.springframework.org/schema/security"> 
     <intercept-url pattern="/sparklr/**" access="ROLE_USER" /> 
     <intercept-url pattern="/facebook/**" access="ROLE_USER" /> 
     <intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" /> 

     <form-login authentication-failure-url="/login.jsp?authentication_error=true" default-target-url="/index.jsp" 
       login-page="/login.jsp" login-processing-url="/login.do" /> 
     <logout logout-success-url="/index.jsp" logout-url="/logout.do" /> 
     <anonymous /> 
     <custom-filter ref="oauth2ClientFilter" after="EXCEPTION_TRANSLATION_FILTER" /> 
    </http> 

    <authentication-manager xmlns="http://www.springframework.org/schema/security"> 
     <authentication-provider> 
      <user-service> 
       <user name="marissa" password="wombat" authorities="ROLE_USER" /> 
       <user name="sam" password="kangaroo" authorities="ROLE_USER" /> 
      </user-service> 
     </authentication-provider> 
    </authentication-manager> 

    <!--apply the oauth client context --> 
    <oauth:client id="oauth2ClientFilter" /> 

    <!-- define an oauth 2 resource for sparklr --> 
    <oauth:resource id="sparklr" type="client_credentials" client-id="tonr" client-secret="secret" 
      access-token-uri="${accessTokenUri}" scope="read,write" /> 

    <!--define an oauth 2 resource for trusted client on sparklr --> 
    <oauth:resource id="trusted" type="client_credentials" client-id="my-client-with-registered-redirect" 
      access-token-uri="${accessTokenUri}" scope="trust" /> 

    <!--define an oauth 2 resource for facebook. according to the facebook docs, the 'client-id' is the App ID, and the 'client-secret' 
     is the App Secret --> 
    <oauth:resource id="facebook" type="authorization_code" client-id="233668646673605" client-secret="33b17e044ee6a4fa383f46ec6e28ea1d" 
      authentication-scheme="query" access-token-uri="https://graph.facebook.com/oauth/access_token" user-authorization-uri="https://www.facebook.com/dialog/oauth" 
      token-name="oauth_token" client-authentication-scheme="form" /> 

    <context:property-placeholder location="classpath:/sparklr.properties" /> 

    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"> 
     <property name="converters"> 
      <set> 
       <bean class="org.springframework.security.oauth.examples.tonr.converter.AccessTokenRequestConverter" /> 
      </set> 
     </property> 
    </bean> 

    <mvc:default-servlet-handler /> 

    <mvc:annotation-driven> 
     <mvc:message-converters> 
      <bean class="org.springframework.http.converter.BufferedImageHttpMessageConverter" /> 
     </mvc:message-converters> 
    </mvc:annotation-driven> 

    <bean id="contentViewResolver" class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"> 
     <property name="mediaTypes"> 
      <map> 
       <entry key="json" value="application/json" /> 
      </map> 
     </property> 
     <property name="defaultViews"> 
      <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" /> 
     </property> 
    </bean> 

    <!--Basic application beans. --> 
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 
     <property name="prefix" value="/WEB-INF/jsp/" /> 
     <property name="suffix" value=".jsp" /> 
    </bean> 

    <bean id="sparklrController" class="org.springframework.security.oauth.examples.tonr.mvc.SparklrController"> 
     <property name="sparklrService" ref="sparklrService" /> 
    </bean> 

    <bean id="facebookController" class="org.springframework.security.oauth.examples.tonr.mvc.FacebookController"> 
     <property name="facebookRestTemplate"> 
      <oauth:rest-template resource="facebook"> 
       <property name="messageConverters"> 
        <list> 
         <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"> 
          <property name="supportedMediaTypes"> 
           <list> 
            <bean class="org.springframework.http.MediaType"> 
             <!--facebook sends its json as text/javascript for some reason --> 
             <constructor-arg value="text" /> 
             <constructor-arg value="javascript" /> 
            </bean> 
            <bean class="org.springframework.http.MediaType"> 
             <constructor-arg value="application" /> 
             <constructor-arg value="json" /> 
            </bean> 
           </list> 
          </property> 
         </bean> 
        </list> 
       </property> 
      </oauth:rest-template> 
     </property> 
    </bean> 

    <bean id="sparklrService" class="org.springframework.security.oauth.examples.tonr.impl.SparklrServiceImpl"> 
     <property name="sparklrPhotoListURL" value="${sparklrPhotoListURL}" /> 
     <property name="sparklrTrustedMessageURL" value="${sparklrTrustedMessageURL}" /> 
     <property name="sparklrPhotoURLPattern" value="${sparklrPhotoURLPattern}" /> 
     <property name="sparklrRestTemplate"> 
      <oauth:rest-template resource="sparklr" /> 
     </property> 
     <property name="trustedClientRestTemplate"> 
      <oauth:rest-template resource="trusted" /> 
     </property> 
    </bean> 

</beans> 

嘗試驗證TONR應用程序時,我收到以下錯誤在sparklr上應用:

HTTP狀態500 - 請求處理失敗;嵌套的例外是 錯誤=「ACCESS_DENIED」,ERROR_DESCRIPTION =「錯誤請求訪問 令牌。

我希望有人能幫助我。謝謝

+0

你會得到500錯誤,所以有服務器上的任何stacktrace?無論如何,你能否提供你所做的令牌請求信息? –

+0

@luizcarlosfx我需要你的幫助,我試圖使用oauth2與休息和使用基於Java的配置的Web應用程序。可以使用oauth進行WEB嗎? –

+0

@HarmeetSingh在這裏有一個示例:https://github.com/spring-projects/spring-security-oauth/tree/master/spring-security-oauth2使用spring security oauth2。所有配置都使用java代碼完成,這比xml配置簡單得多。是的,當然可以使用oauth進行WEB。此示例演示了這個 – luizcarlosfx

回答

3

您可以嘗試允許對/oauth/token端點匿名訪問。這就是隻有這樣,我能得到我的client_credentials流工作。

改變這一行

<intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" />

這個

<intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_ANONYMOUSLY" />

並刪除這一行:

<anonymous enabled="false" />

希望有所幫助。

+0

我已經解決了這個問題。我升級所有我的彈簧配置爲java配置只寫需要的部分,這工作正常。這個例子有很多我不需要的代碼。但感謝您的回答 – luizcarlosfx

-4

通過

<oauth:resource id="sparklr" type="authorization_code" client-id="tonr" client-secret="secret" 
     access-token-uri="${accessTokenUri}" scope="read,write" /> 

錯誤替換該行

<oauth:resource id="sparklr" type="client_credentials" client-id="tonr" client-secret="secret" 
     access-token-uri="${accessTokenUri}" scope="read,write" /> 

是EL型client_credentials和authorization_code更換,將正常工作。

+0

正如我在問題中所說的,我想使用oauth2與客戶端憑證流程,而不是授權代碼流程。但我不是downvoter – luizcarlosfx