2012-10-05 34 views
5

Me gustaría implementar OAuth 2.0 para mi proyecto Spring 3.1 y RESTEasy. El proyecto es un servicio REST basado en JSON. Uso Spring Security 3.1 y spring-security-oauth2 versión 1.0.0.RC2 (que debería ser la última). Hasta ahora tengo la configuración de seguridad de primavera con la configuración predeterminada. También tengo una configuración muy básica (por defecto) para OAuth 2.0.No hay ningún adaptador para el error del controlador para puntos finales del proveedor oauth2

Utilicé el servicio REST antes, funciona perfecto. La seguridad de Spring también parece funcionar bien. Me redireccionan a una página de inicio de sesión si abro un enlace a mi servicio REST. Después de iniciar sesión, puedo hacer llamadas REST que dan el resultado esperado.

Al abrir het URLs localhost:8080/tools-service/oauth/token o localhost:8080/tools-service/oauth/error, para probar la OAuth, me sale un error 500. el siguiente error se muestran cuando accedo a /oauth/token. El error para /oauth/error es simular.

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?

Si estoy en lo correcto esto implica que hay un error en la función TokenEndpoint.getAccessToken? Como esa clase es parte del marco Spring (y busqué el código, que se ve bien), no creo que el problema esté realmente relacionado con esas clases. Lo cual me deja desorientado.

Ahora me gustaría saber por qué sucede esto y cómo puedo solucionarlo. Consideré el hecho de que yo, tal vez, no puedo visitar esas URL en un navegador. Sin embargo, si pruebo lo mismo con Sparklr2 (the Spring OAuth 2.0 sample application), recibo un mensaje XML (para/oauth2/token) y una página de error (para/oauth2/error), que es como se esperaba.

Cualquier ayuda o consejo sería muy apreciado.


Seguridad fragmento relacionado de 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> 

Mi contexto de aplicación carga el siguiente archivo de seguridad-config.xml creé:

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

La aplicación CollectorClientDetails sólo es ficticia código:

@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; 
    } 

} 

Respuesta

11

Después de dejar que este problema se enfriara durante unos días, realicé una nueva búsqueda en Google. Esto me llevó al foro Spring Source: http://forum.springsource.org/showthread.php?130684-OAuth2-No-adapter-for-handler-exception.

Aquí encontré que banifou tenía el mismo problema. David Syer respondió a la pregunta de esta manera:

Parece que ha quitado el <mvc:annnotation-driven/> del sparklr vainilla. Creo que si vuelves a colocarlo en el adaptador del controlador se definirá para ti.

La seguridad de Spring se basa en el marco Spring MVC para tratar las solicitudes y respuestas. Por lo tanto, el marco de MVC debe incluirse y configurarse correctamente para que OAuth, la seguridad de Spring, funcione.

La solución es que he añadido 2 etiquetas a mi contexto de aplicación:

  • <mvc:annotation-driven />

Hacer el framwork MVC listo para manejar las anotaciones. Esto hace que @FrameworkEndpoint funcione correctamente. La tarde que se está utilizando en el public class TokenEndpoint, que dio el error 500.

  • <mvc:default-servlet-handler />

Este controlador reenviará todas las peticiones al servlet por defecto. Por lo tanto, es importante que permanezca último en el orden de todos los demás HandlersMappings de URL. Ese será el caso si usa <mvc:annotation-driven>. (Cita de la documentación de la primavera.)

Más información se puede encontrar aquí: annotation-driven, default-servlet-handler.

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

    <context:component-scan base-package="be.collectortools.rest"/> 
    <context:annotation-config/> 

    <mvc:annotation-driven /> 
    <mvc:default-servlet-handler /> 

    <import resource="classpath:springmvc-resteasy.xml"/> 
    <import resource="mongo-config.xml"/> 
    <import resource="security-config.xml"/> 

</beans> 
+4

Me alegra que haya otros que respondan a su propia pregunta de esta manera. Este es un buen ejemplo de que, por oscuro que sea su problema, siempre hay al menos otro usuario que experimenta lo mismo. Si pudiera comprarte una cerveza, lo haría, pero al menos tengo un voto al votante :-) – Joe

+0

Vertongen, tuve el mismo problema, todos los resultados de Google relacionados fueron leídos, pero solo el tuyo resolvió mi problema, The faltaba en mi código. ¡Gracias por responder tu propia pregunta y ayudarme! – szpetip

+0

Su bienvenida. Estoy feliz de que esto siga siendo útil después de todo este tiempo. – Vertongen

Cuestiones relacionadas