2012-06-24 15 views
18

Estoy trabajando en una aplicación, donde el servidor y el cliente que consume API residen en dominios diferentes, por lo que me gustaría usar CORS. Para hacerlo, tengo que establecer cabeceras HTTP correspondientes en la respuesta del servidor:Cómo enviar encabezados CORS con Ideario si el usuario no está autorizado (respuesta 401)

def cors_set_access_control_headers 
    headers['Access-Control-Allow-Origin'] = 'http://localhost' 
    headers['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS' 
    headers['Access-Control-Allow-Headers'] = '*, X-Requested-With, X-Prototype-Version, X-CSRF-Token, Content-Type' 
    headers['Access-Control-Max-Age'] = "1728000" 
end 

Este método se utiliza como before_filter en ApplicationController.

Para algunos recursos, el usuario debe estar autenticado y autorizado. Las solicitudes se realizan a través de XHR/Ajax. Por lo tanto, si el usuario no está autenticado, Devise enviará una respuesta 401 al cliente, en lugar de redirigir a una página de inicio de sesión. Pero el filtro para establecer los encabezados CORS no se usa para esa respuesta. Por lo tanto, la respuesta 401 no se envía al cliente. Quiero capturar y usar la respuesta 401 en el cliente.

Actualmente estoy usando una solución al no utilizar los métodos de autenticación Idear, pero un fragmento de autenticación personalizado:

def authenticate_cors_user 
    if request.xhr? && !user_signed_in? 
    error = { :error => "You must be logged in." } 
    render params[:format].to_sym => error, :status => 401 
    end 
end 

Esto se establece como before_filter en ApplicationController, también. De esta forma, el filtro para configurar encabezados CORS se activa y todo funciona bien.

Preferiría usar el comportamiento predeterminado de Devise, pero los encabezados CORS tendrían que establecerse en la respuesta 401. ¿Como hacer esto? ¿Tengo que configurar warden para eso?

¿Cómo podrían los encabezados CORS establecerse para la respuesta 401 generada por Devise en lugar de crear mi propia respuesta?

+0

Todavía no tenemos una solución para eso. Para dar un poco más de contexto, revisa la entrada de mi blog sobre cómo estoy usando esto: http://nils-blum-oeste.net/cors-api-with-oauth2-authentication-using-rails-and-angularjs –

Respuesta

21

he usado con éxito el bastidor-cors joya https://github.com/cyu/rack-cors y delineó mi experiencia en my blog.

cuenta es el final: Especificar el fin de middleware por lo cors controlador está delante de guardia:

config.middleware.insert_before Warden::Manager, Rack::Cors 
+0

Su enfoque funciona muy bien, ¡gracias! Sin embargo, curiosamente, me tomó algo de tiempo y algo de investigación adicional para darme cuenta, de que realmente tengo que cambiar solo una línea de código en la configuración para hacer que 'Devise' y' rack-cors' funcionen juntos. –

+0

Hey @ digger69. ¿Tuviste problemas con otras excepciones? Por ejemplo: si tiro una excepción en mi acción 'def índice; levantar 'error'; end' - Rails no devuelve los encabezados CORS (rack-cors). ¿Funciona para ti? –

+4

PD: también podría usar 'config.middleware.insert 0, Rack :: Cors' para garantizar que' Rack :: Cors' se insertará antes que cualquier otro middleware posible. –

0

En general, no nos han gustado los encabezados CORS. Preferimos usar HAProxy para redirigir.

Con HAProxy puede configurar todas las solicitudes que lleguen a website.com/api/ para que sean redirigidas internamente a su máquina de rieles.

frontend main *:80 
    acl api  path_beg -i /api 
    acl app  path_beg -i /app 
backend app_backend 
    reqrep ^([^\ ]*)\ /app/(.*) \1\ /\2 
    balance roundrobin 
    server app_files smartphoneapp.localhost:8000 
backend api_backend 
    reqrep ^([^\ ]*)\ /api/(.*) \1\ /\2 
    balance roundrobin 
    server app_api localhost:3000 
+0

CORS could ser burlado usando un proxy, seguro. Pero aún así debe haber una forma de manejar esto bien con Devise/warden, supongo. –

+0

Eche un vistazo a este artículo: http://www.tsheffler.com/blog/?p=428 – Hendrik

Cuestiones relacionadas