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