Spring-OAUTH2.0:调用 /oauth/token 时没有可用资源错误
Posted
技术标签:
【中文标题】Spring-OAUTH2.0:调用 /oauth/token 时没有可用资源错误【英文标题】:Spring-OAUTH2.0: No resource available error on calling /oauth/token 【发布时间】:2014-11-23 14:01:14 【问题描述】:我们有一组需要使用 OAUTH2.0 保护的 ReST Web 服务。我正在尝试通过参考以下资源来实现 OAUTH2.0:
Spring-security context setup for 2-legged (client credentials) OAuth2 server http://www.e-zest.net/blog/rest-authentication-using-oauth-2-0-resource-owner-password-flow-protocol/但是,在完成所需的配置后,我试图点击 URL http://localhost:8080/project-name/oauth/token?grant_type=password&client_id=client1&client_secret=client1&username=admin&password=admin
Tomcat 抛出错误 - The requested resource is not available.
当我尝试在ClientDetailsServiceImpl.java
中放置一个调试点时,流程以正确的细节出现。无法理解我在这里做错了什么。任何建议表示赞赏。 TIA。
以下是文件详细信息:Spring 配置文件
<?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.2.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd ">
<http pattern="/oauth/token" create-session="stateless"
authentication-manager-ref="authenticationManager"
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" />
<custom-filter ref="clientCredentialsTokenEndpointFilter" before="BASIC_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<http pattern="/resources/**" create-session="never"
entry-point-ref="oauthAuthenticationEntryPoint"
xmlns="http://www.springframework.org/schema/security">
<anonymous enabled="false" />
<intercept-url pattern="/resources/**" method="GET" access="IS_AUTHENTICATED_FULLY" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<http pattern="/logout" create-session="never"
entry-point-ref="oauthAuthenticationEntryPoint"
xmlns="http://www.springframework.org/schema/security">
<anonymous enabled="false" />
<intercept-url pattern="/logout" method="GET" />
<sec:logout invalidate-session="true" logout-url="/logout" success-handler-ref="logoutSuccessHandler" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<bean id="logoutSuccessHandler" class="in.test.server.security.oauth.LogoutImpl" >
<property name="tokenstore" ref="tokenStore"></property>
</bean>
<bean id="oauthAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
</bean>
<bean id="clientAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="springsec/client" />
<property name="typeName" value="Basic" />
</bean>
<bean id="oauthAccessDeniedHandler"
class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler">
</bean>
<bean id="clientCredentialsTokenEndpointFilter"
class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<property name="authenticationManager" ref="authenticationManager" />
</bean>
<authentication-manager alias="authenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider user-service-ref="clientDetailsUserService" />
</authentication-manager>
<bean id="clientDetailsUserService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="clientDetails" />
</bean>
<bean id="clientDetails" class="in.test.server.security.oauth.ClientDetailsServiceImpl"/>
<authentication-manager id="userAuthenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider ref="customUserAuthenticationProvider">
</authentication-provider>
</authentication-manager>
<bean id="customUserAuthenticationProvider"
class="in.test.server.security.oauth.CustomUserAuthenticationProvider">
</bean>
<oauth:authorization-server
client-details-service-ref="clientDetails" token-services-ref="tokenServices">
<oauth:authorization-code />
<oauth:implicit/>
<oauth:refresh-token/>
<oauth:client-credentials />
<oauth:password authentication-manager-ref="userAuthenticationManager"/>
</oauth:authorization-server>
<oauth:resource-server id="resourceServerFilter"
resource-id="springsec" token-services-ref="tokenServices" />
<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="accessTokenValiditySeconds" value="300000"></property>
<property name="clientDetailsService" ref="clientDetails" />
</bean>
<mvc:annotation-driven /> <!-- Declares explicit support for annotation-driven MVC controllers @RequestMapping, @Controller -->
<mvc:default-servlet-handler />
<bean id="MyResource" class="in.test.server.resource.CommonResource"></bean>
</beans>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>in-test-gcp-server</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:applicationContext.xml
classpath:security-config.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<servlet>
<servlet-name>jersey-serlvet</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>in.test.server.resource.TestRSApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-serlvet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Added for 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>
</web-app>
ClientDetailsServiceImpl.java
package in.test.server.security.oauth;
import java.util.ArrayList;
import java.util.List;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.security.oauth2.provider.BaseClientDetails;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.NoSuchClientException;
import org.springframework.stereotype.Service;
@Service
public class ClientDetailsServiceImpl implements ClientDetailsService
public ClientDetails loadClientByClientId(String clientId)
throws OAuth2Exception
if (clientId.equals("client1"))
List<String> authorizedGrantTypes=new ArrayList();
authorizedGrantTypes.add("password");
authorizedGrantTypes.add("refresh_token");
authorizedGrantTypes.add("client_credentials");
BaseClientDetails clientDetails = new BaseClientDetails();
clientDetails.setClientId("client1");
clientDetails.setClientSecret("client1");
clientDetails.setAuthorizedGrantTypes(authorizedGrantTypes);
return clientDetails;
else if(clientId.equals("client2"))
List<String> authorizedGrantTypes=new ArrayList();
authorizedGrantTypes.add("password");
authorizedGrantTypes.add("refresh_token");
authorizedGrantTypes.add("client_credentials");
BaseClientDetails clientDetails = new BaseClientDetails();
clientDetails.setClientId("client2");
clientDetails.setClientSecret("client2");
clientDetails.setAuthorizedGrantTypes(authorizedGrantTypes);
return clientDetails;
else
throw new NoSuchClientException("No client with requested id: "
+ clientId);
CustomUserAuthenticationProvider.java
package in.test.server.security.oauth;
import java.util.ArrayList;
import java.util.List;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
public class CustomUserAuthenticationProvider implements AuthenticationProvider
public Authentication authenticate(Authentication authentication)
throws AuthenticationException
if(authentication.getPrincipal().equals("user")&& authentication.getCredentials().equals("user"))
List<GrantedAuthority> grantedAuthorities = new ArrayList();
UsernamePasswordAuthenticationToken auth=new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), authentication.getCredentials(),grantedAuthorities);
return auth;
else if(authentication.getPrincipal().equals("admin")&& authentication.getCredentials().equals("admin"))
List<GrantedAuthority> grantedAuthorities = new ArrayList();
UsernamePasswordAuthenticationToken auth=new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), authentication.getCredentials(),grantedAuthorities);
return auth;
else if(authentication.getPrincipal().equals("user1")&& authentication.getCredentials().equals("user1"))
List<GrantedAuthority> grantedAuthorities = new ArrayList();
UsernamePasswordAuthenticationToken auth=new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), authentication.getCredentials(),grantedAuthorities);
return auth;
else
throw new BadCredentialsException("Bad User Credentials.");
public boolean supports(Class<?> arg0)
// TODO Auto-generated method stub
return true;
【问题讨论】:
你成功了吗? 【参考方案1】:在您的 web.xml 中,您需要一个带有指向 /oauth/token 的 url-pattern 属性的 servlet-mapping 标记
类似:
<servlet-mapping>
<servlet-name>spring <!-- Or whatever your dispatch servlet is called --></servlet-name>
<url-pattern>/oauth/token</url-pattern>
</servlet-mapping>
【讨论】:
以上是关于Spring-OAUTH2.0:调用 /oauth/token 时没有可用资源错误的主要内容,如果未能解决你的问题,请参考以下文章
如何集成 AngularJS 和 Spring-OAuth2?
为啥没有spring-oauth2的starter pom?
如何将 Angular 2 应用程序与 spring-oauth2 服务器连接?
Spring - oauth 2 - 无法将访问令牌转换为 JSON
Spring - OAuth2AccessTokenSupport 覆盖其余模板自定义 SSLSocketFactory