5

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

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

此外,我希望服务器(设计)设置一个 cookie,以便基于 cookie 的身份验证工作,我也可以通过非 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像这样的 Header:

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=/

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

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

我不明白,为什么 cookie 设置的标头看起来很好,但 cookie 没有设置?

任何人都可以启发我吗?

问候菲利克斯

4

1 回答 1

5

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

所以在我的情况下解决问题的唯一方法是:让用户登录到 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,cookie 被设置,即使 JS 应用程序是从a.domain.com. 不要忘记:当您设置 Access-Control-Allow-Credentials 时,您不能对 Access-Control-Allow-Origin 使用通配符(无论如何您都不应该这样做)。

于 2013-08-23T14:13:49.277 回答