为什么没有在XHR请求上设置设计cookie?

时间:2013-08-23 10:49:05

标签: ruby-on-rails cookies devise xmlhttprequest ruby-on-rails-4

我在一个提供JSON API的Rails4应用程序上使用设计。我修补了设计,因此它通过HTTP头而不是URL参数接受身份验证令牌。这非常有效。

基于该API的JS单页面应用程序运行良好。我可以对用户进行身份验证,并在应用程序内请求此用户资源。

此外,我希望服务器(设计)设置一个cookie,以便基于cookie的auth工作,我也可以通过非XHR请求请求用户私有资源。这不起作用,我不知道为什么。

我是我的设计初始化者:

config.http_authenticatable_on_xhr = true

在我的session_store初始化程序中,我设置了:

MyApp::Application.config.session_store :cookie_store, key: '_myapp_session', domain: :all, httponly: false, secure: false

当我在Chrome中运行我的单页应用并检查网络请求时,我可以看到对服务器端资源请求的每个响应都包含Set-Cookie标头,如下所示:

HTTP/1.1 200 OK
X-Frame-Options: SAMEORIGIN
X-Xss-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Ua-Compatible: chrome=1
Access-Control-Allow-Origin: * //dont give me shelter
Access-Control-Allow-Methods: POST, PUT, GET, OPTIONS, DELETE
Access-Control-Max-Age: 1728000
X-Meta-Request-Version: 0.2.8
Etag: "7b64cd327b9ff8dce6bb8b616aeee2b8"
Cache-Control: max-age=0, private, must-revalidate
X-Request-Id: 1d6be45e-ce45-40fd-b03b-358644826955
X-Runtime: 0.283514
Server: WEBrick/1.3.1 (Ruby/2.0.0/2013-06-27)
Date: Fri, 23 Aug 2013 10:36:04 GMT
Connection: Keep-Alive
Set-Cookie: _myapp_session=NndJcUd5QUJmRktkSkdTVTk1NTF3UHVKaW85QkVmTmpqZEM4Q3BqUW5ORzNyNG5HWmlnSWc5Yy83Nk16c3Q0dk1iVXQ0Q2JqTE1qZWZoaDgxNW1RQnErOHhsVG9rdEQ4cU1CNGsyNWsrVlk0OXlLRGo5c1BiN3NkdFlRdWJHVXBDamI1U1BrdlQ3Mmw3OWNZVWJkWGI1UWZqNDJ1VldxL0xvYkkwYVd5aHBYaU5sOElkZ3NSRXZVdGxlWHQxY1FteFh1OGU3NHowYU0xYTRLK2xuTEN4KzhzR2pjR25YWlZVSTZtZDkvUnZXbz0tLXJKMXNlV1gvcHFuaG5jU3YvNUJhSnc9PQ%3D%3D--5ecf40e2a678b467b77aa0c56494be8e079641d2; domain=.myapp.dev; path=/

我的应用程序从端口9000上的app.myapp.dev提供,并在端口3000上的api.myapp.dev处请求API。由于正确的CORS配置,这可以正常工作。

如果我在Cookies下的Chrome资源面板中查看,则不会设置Cookie。由于没有cookie,因此api.myapp.net的每个非XHR请求都不会对用户进行身份验证。

我不明白,为什么cookie设置标题似乎没问题,但cookie没有设置?

任何人都可以启发我吗?

此致 菲利克斯

1 个答案:

答案 0 :(得分:2)

好吧,正如我今天发现的那样,可以从a.domain.com提供一个JS应用程序并让它从启用了CORS的b.domain.com获取JSON数据,但是{{1}发送的cookie }将不会被设置。某种邪恶可以在这里继续。

因此,在我的案例中解决问题的唯一方法是:让用户登录JS应用程序,将他重定向到b.domain.com的端点并添加身份验证令牌。 b.domain.com处的服务器记录用户,现在可以设置cookie并将用户重定向到JS应用程序。

这是一个可怕的解决方案,导致应用程序加载两次,但只要您从另一个子域提供您的应用程序而不是您的API,似乎没有更好的解决方案。对任何人都很开放。

<强>更新

如果您控制服务器标头,确实可以设置跨域cookie。

在我的案例中解决了问题的是:

b将其他响应标头b.domain.com设置为true。此外,需要修补内部主干同步,以便传递的选项对象获得带Access-Control-Allow-Credentials的键xhrFields。就是这样。当withCredentials:trueb.domain.com标头响应时,即使JS应用程序是从Set-Cookie发送的,也会设置Cookie。不要忘记:当你设置Access-Control-Allow-Credentials时,你不能使用通配符来访问Access-Control-Allow-Origin(你不应该使用它)。