如果用户未经授权,如何使用Devise发送CORS头(401响应)

时间:2012-06-24 11:31:23

标签: ruby-on-rails rest devise cross-domain cors

我正在开发一个app,其中服务器和api消费客户端位于不同的域下,所以我想使用CORS。为此,我必须在服务器响应中设置相应的http标头:

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

此方法用作before_filter中的ApplicationController

对于某些资源,用户必须经过身份验证和授权。请求通过XHR / Ajax完成。因此,如果用户未经过身份验证,Devise将向客户端发送401响应,而不是重定向到登录页面。但是用于设置CORS头的过滤器不用于该响应。因此401响应不会发送给客户端。我想在客户端捕获并使用401响应。

目前,我通过不使用Devise身份验证方法,但使用自定义身份验证代码段来使用解决方法:

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

这也在before_filter中设为ApplicationController。这样,设置CORS标头的过滤器就会被触发,一切正常。

我更喜欢使用Devise的默认行为,但必须在401响应中设置CORS头。这该怎么做?我必须为此配置warden吗?

如何为Devise生成的401响应设置CORS标头,而不是创建自己的响应?

2 个答案:

答案 0 :(得分:21)

我成功使用了rack-cors gem https://github.com/cyu/rack-cors并概述了我在my blog上的体验。

Punchline:指定中间件订单,因此cors处理程序在warden之前:

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

答案 1 :(得分:0)

我们通常不喜欢CORS标头。我们更喜欢使用HAProxy来重定向。

使用HAProxy,您可以设置所有来到website.com/api/的请求,以便在内部重定向到您的rails计算机。

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