我想为我的 Spring 3.1 和RESTEasy项目实现 OAuth 2.0。该项目是一个基于 JSON 的 REST 服务。我使用 Spring Security 3.1 和 spring-security-oauth2 版本 1.0.0.RC2(应该是最新的)。到目前为止,我已经使用默认设置进行了 spring 安全设置。我对 OAuth 2.0 也有非常基本的(默认)配置。
我之前用过 REST 服务,效果很好。Spring 安全性似乎也可以正常工作。如果我打开指向我的 REST 服务的链接,我将被重定向到登录页面。登录后,我可以进行 REST 调用,得到预期的结果。
当我打开 het urllocalhost:8080/tools-service/oauth/token
或localhost:8080/tools-service/oauth/error
测试 OAuth 时,我收到错误 500。当我访问时显示以下错误/oauth/token
。的错误/oauth/error
是相似的。
HTTP Status 500 - No adapter for handler [public org.springframework.http.ResponseEntity org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.getAccessToken(java.security.Principal,java.lang.String,java.util.Map)]: Does your handler implement a supported interface like Controller?
如果我是正确的,这意味着TokenEndpoint.getAccessToken
函数中存在错误?由于该类是 Spring 框架的一部分(我查看了代码,看起来不错)我认为问题实际上与这些类无关。这让我一无所知。
现在我想知道为什么会发生这种情况以及如何解决这个问题。我考虑了这样一个事实,即我可能不允许在浏览器中访问这些 URL。但是,如果我尝试对 Sparklr2(Spring OAuth 2.0 示例应用程序)进行相同操作,我会收到一条 XML 消息(用于 /oauth2/token)和一个错误页面(用于 /oauth2/error),这与预期的一样。
任何帮助或提示将不胜感激。
来自 web.xml 的安全相关片段:
<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>
我的应用程序上下文加载了我创建的以下 security-config.xml 文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:sec="http://www.springframework.org/schema/security"
xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-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/security/oauth2
http://www.springframework.org/schema/security/spring-security-oauth2.xsd">
<sec:http auto-config="true">
<sec:intercept-url pattern="/**" access="ROLE_USER" />
</sec:http>
<sec:authentication-manager>
<sec:authentication-provider>
<sec:user-service>
<sec:user name="user1" password="test123" authorities="ROLE_USER" />
<sec:user name="user2" password="hello123" authorities="ROLE_USER" />
</sec:user-service>
</sec:authentication-provider>
</sec:authentication-manager>
<sec:global-method-security pre-post-annotations="enabled" proxy-target-class="true">
<sec:expression-handler ref="oauthExpressionHandler" />
</sec:global-method-security>
<bean id="clientDetailsService" class="be.collectortools.rest.service.security.CollectorDetailsServiceImpl" />
<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="clientDetailsService"/>
</bean>
<oauth:authorization-server
client-details-service-ref="clientDetailsService"
token-services-ref="tokenServices">
<oauth:authorization-code />
<oauth:implicit />
<oauth:refresh-token />
<oauth:client-credentials />
<oauth:password />
</oauth:authorization-server>
<oauth:expression-handler id="oauthExpressionHandler" />
</beans>
CollectorClientDetails 实现只是虚拟代码:
@Service
public class CollectorDetailsServiceImpl implements ClientDetailsService {
@Resource
private CollectorClientDetailsRepository collectorClientDetailsRepository;
@Override
public ClientDetails loadClientByClientId(final String clientId) throws OAuth2Exception {
CollectorClientDetails dummyClient = new CollectorClientDetails();
dummyClient.setClientId(clientId);
return dummyClient;
}
}