10

He creado un back-end REST API con Spring MVC y asegurado con autenticación básica con Spring Security.JQuery dominio cruzado auth call

Me gustaría hacer la llamada ajax de dominio cruzado a la API REST de los clientes de Javascript. No quiero usar JSONP porque no quiero limitarme a las llamadas GET. Yo uso CORS y he puesto los encabezados correctos en el lado del servidor.

Supongamos que mi API REST está en el dominio localhost: 8087 y mi cliente en el host local: 8086, que es una llamada de dominio cruzado.

En mi cliente Javascript, hago llamada AJAX con jQuery:

<script> 
     $.ajax ({ 
      url: "http://localhost:8087/SpringMVC/users/user1", 
      beforeSend: function (xhr) { xhr.setRequestHeader ("Authorization", "Basic xxxxxxxxxxxx"); }, 
      success: function(val) { console.log(val); alert("success" + val); }, 
      error: function(val) { console.log(val); alert("error" + val); } 
     }); 
</script> 

Mi problema es que jQuery no envía el encabezado de autorización en la solicitud HTTP y no sé qué. No entiendo porque lo hago en el método beforeSend, por lo que debe estar dentro de la solicitud HTTP. Resultado: tengo un error 401.

Cuando intento la secuencia de comandos del mismo dominio localhost: 8087, que ya no es de dominio cruzado, no tengo ningún problema.

¿Cómo es posible?

Mi script es solo una prueba. No tengo la intención de poner mi nombre de usuario/contraseña en el lado del cliente. Pero quiero probar cómo hacer llamadas ajax a una API REST protegida con autenticación básica. Imagino que tengo que enviar por el lado del servidor para asegurar mi nombre de usuario/contraseña, la API REST me envía una cookie y ya no necesito pasar el nombre de usuario/contraseña para mis próximas llamadas ajax a la API REST. Estoy en lo correcto?

He probado mi API REST con el cliente REST avanzado de Chrome y funciona de esa manera. Para la primera solicitud, necesito pasar el encabezado de autorización. Entonces no es necesario. ¿Debería funcionar también así con mi cliente web javascript? Tengo la intención de usar Node.JS con Backbone para construirlo.

Muchas gracias.

EDIT2: Parece ser realmente un problema del navegador CORS. He agregado el encabezado Access-Control-Allow-Methods para el método OPTIONS en el lado del servidor y funciona en Chrome. Tengo acceso a la respuesta JSON sin ningún error. Pero aún necesito usar el encabezado de autorización para las próximas solicitudes. ¿Cómo decirle a jQuery que use la cookie enviada?

y cuando intento con Firefox 11, que no tienen acceso a la respuesta JSON y tengo el error:

"NetworkError: 401 Non-Autorisé - http://localhost:8087/SpringMVC/users/user1" 
+0

¿Estás base 64 que codifican su nombre de usuario/contraseña? –

+0

Sí, lo puse xxxxxxxx en lugar del nombre de usuario real: contraseña. – rico

Respuesta

8

Al parecer, Chrome y Firefox tratan entre dominios pide un poco diferente. Antes de realizar la solicitud de dominio cruzado, hacen lo que se denomina una solicitud de verificación previa con el método HTTP OPTIONS. La diferencia entre Chrome y Firefox es que Chrome también envía el encabezado de Autorización con las credenciales, mientras que Firefox no lo hace.

Luego, sigue siendo un problema de configuración de Spring Security. Mi url/users/* está asegurado para todos los métodos HTTP, incluidas las OPCIONES. En el caso de Firefox, como el encabezado de Autorización no se envía, mi solicitud no está autorizada. Si restrinjo mi url/users/* seguro al método GET solamente, entonces funciona perfectamente para Firefox.Así que tuve que agregar sólo que en mi seguridad de configuración de primavera:

<intercept-url pattern="https://stackoverflow.com/users/*" access="isAuthenticated()" method="GET"/> 

Después, tengo la opción: puedo añadir otros métodos para asegurar en la intersección-url, excepto OPCIONES, o puedo restringir el HTTP Llamada de método a GET en mi controlador Spring MVC, que incluso tratará mis llamadas OPTIONS de acuerdo con Javadoc. Elegí la segunda solución. Pero si alguien encuentra una solución para obligar a Firefox a enviar las credenciales como Chrome, sería genial y yo elegiría esta.

2

Otra opción para el escenario de configuración de la primavera de Seguridad presentado por Rico sería: OPCIONES

<http ... use-expressions="true"> 
    <intercept-url pattern="https://stackoverflow.com/users/*" access="permitAll" method="OPTIONS"/> 
    <intercept-url pattern="https://stackoverflow.com/users/*" access="isAuthenticated()"/> 
    ... 
</http> 

peticiones HTTP pasarán siempre a través de la autenticación y cualquier otro método HTTP no.

Tenga en cuenta que el atributo XML use-expressions establecido en verdadero en <http> elemento. Seguridad primavera y luego esperar los access atributos de los elementos para <intercept-url> contienen Primavera EL expresiones, como permitAll y isAuthenticated().

Cuestiones relacionadas