2014-03-04 110 views
1

我正在嘗試使用Resteasy和Spring構建REST服務器/提供程序,並希望使用OAuth 2來保護一些API。據我所知,我應該使API公開URI以生成OAuth令牌(例如/ oauth/token),然後使用它訪問受保護的部分。Resteasy/Spring Security + Oauth 2.0 - 錯誤404

下面是我使用Spring Security及其OAuth2支持的代碼,我試圖在保護/ ws/v1/oauth/**的同時公開單個/ oauth/token URI。當我嘗試訪問任何這些URI而不發送憑據時,我得到安全性「Bad Credentials request」(正如我所期望的),但是當我試圖在/ oauth/token URI上實際輸入corret憑證時(通過POST方法)我遇到了一個HTTP 404錯誤。

我的web.xml代碼。

<context-param> 
    <param-name>contextConfigLocation</param-name> 
    <param-value> 
     classpath:spring-context.xml 
     classpath:database-context.xml 
     classpath:security-context.xml 
    </param-value> 
</context-param> 

<!-- RestEasy Bootstrap --> 
<listener> 
    <listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class> 
</listener> 

<!-- Spring Bootstrap --> 
<listener> 
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> 
</listener> 

<listener> 
    <listener-class>org.jboss.resteasy.plugins.spring.SpringContextLoaderListener</listener-class> 
</listener> 

<!-- RestEasy Servlet --> 
<servlet> 
    <servlet-name>Resteasy</servlet-name> 
    <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class> 
</servlet> 
<servlet-mapping> 
    <servlet-name>Resteasy</servlet-name> 
    <url-pattern>/ws/*</url-pattern> 
</servlet-mapping> 

<!-- OAuth2/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> 

我的安全上下文。 (我在這裏計算器的例子發現和適應一點)

<oauth:authorization-server client-details-service-ref="clientDetails" token-services-ref="tokenServices"> 
    <oauth:client-credentials /> 
</oauth:authorization-server> 

<sec:authentication-manager alias="clientAuthenticationManager"> 
    <sec:authentication-provider user-service-ref="clientDetailsUserService" /> 
</sec:authentication-manager> 

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

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

<oauth:client-details-service id="clientDetails"> 
    <oauth:client client-id="the_client" authorized-grant-types="client_credentials" 
      authorities="ROLE_READ" secret="1234567890" /> 
    <oauth:client client-id="password_client" authorized-grant-types="password" 
      authorities="ROLE_READ" secret="1234567890" /> 
</oauth:client-details-service> 


<http pattern="/**" 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="/ws/v1/oauth/**" access="ROLE_READ" method="GET" /> 
    <custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" /> 
    <access-denied-handler ref="oauthAccessDeniedHandler" /> 
</http> 

<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="false" /> 
    <property name="clientDetailsService" ref="clientDetails" /> 
    <property name="accessTokenValiditySeconds" value="400000" /> 
    <property name="refreshTokenValiditySeconds" value="0" /> 
</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> 


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

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

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


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

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


<sec:global-method-security pre-post-annotations="enabled" proxy-target-class="true"> 
    <sec:expression-handler ref="oauthExpressionHandler" /> 
</sec:global-method-security> 

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

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

我看到了一些類似的問題,其中春季安全無法將HTTP路徑註冊到上下文,因爲它沒有被通過,但我不知道如何在我的Web.xml中做到這一點,因爲我使用SpringContextLoaderListener而不是ContextLoaderListener(它似乎存在於我找到的所有示例/問題中)。

有關如何讓404錯誤消失的任何提示?

編輯 - 只是爲了澄清,我測試了/ OAuth的/憑證網址與POST和GET

GET例如:

http://127.0.0.1:9999/oauth/token?client_id=the_client&client_secret=1234567890&grant_type=client_credentials 

在這兩種情況下,我得到不正確的憑據/錯誤404

回答

1

TokenEndpoint是Spring MVC @Controller,因此您需要DispatcherServlet來處理請求。這可能意味着您需要完全丟棄ContextLoaderListener(但我不知道SpringContextLoaderListener正在做什麼)並將您的配置移動到servlet(示例here)。幸運的是,默認的servlet映射「/」似乎是開放的,所以如果你安裝了servlet並加載你的配置文件,所有的東西都應該工作。

+0

謝謝戴夫!問題在於缺乏servlet來獲取/ oauth/token映射。還必須在我的上下文中添加spring webmvc註釋,以便OAuth2處理程序能夠正確處理令牌請求。 – lazaruz3

相關問題