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

Geo*_*ieF 5 cookies ruby-on-rails xmlhttprequest devise ruby-on-rails-4

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

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

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

我有我的设计初始化程序:

config.http_authenticatable_on_xhr = true
Run Code Online (Sandbox Code Playgroud)

在我的 session_store 初始值设定项中,我设置了:

MyApp::Application.config.session_store :cookie_store, key: '_myapp_session', domain: :all, httponly: false, secure: false
Run Code Online (Sandbox Code Playgroud)

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

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=/
Run Code Online (Sandbox Code Playgroud)

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

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

我不明白,为什么 cookie 设置标题看起来不错,但 cookie 没有设置?

任何人都可以启发我吗?

问候菲利克斯

Geo*_*ieF 5

好的,正如我目前所发现的,可以在启用 CORS 的情况下交付 JS 应用程序a.domain.com并让它从中获取 JSON 数据b.domain.com,但b.domain.com不会设置发送的 cookie 。这里可能会发生某种邪恶。

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

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

更新

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

在我的情况下解决问题的是:

b.domain.com将额外的响应头设置Access-Control-Allow-Credentials为 true。此外,需要修补内部主干同步,以便传递的选项对象获得xhrFields带有withCredentials:true. 就是这样。当b.domain.com使用Set-Cookie标头响应时,即使 JS 应用程序是从a.domain.com. 不要忘记:当您设置 Access-Control-Allow-Credentials 时,您不能对 Access-Control-Allow-Origin 使用通配符(无论如何您都不应该使用通配符)。