【问题标题】:Why chrome sets cookie on wrong subdomain?为什么 chrome 在错误的子域上设置 cookie?
【发布时间】:2019-07-25 19:11:15
【问题描述】:

我有以下子域:

api.example.com
app1.example.com
app2.example.com

我使用 nginx 作为 Web 服务器来提供所有这些服务。 api.example.com 是我正在开发的 python-flask 应用程序。 app1.example.comapp2.example.com是静态js内容,不是我开发的。

Nginx 配置为允许跨域资源共享:

    if ($request_method = 'OPTIONS') {
            add_header 'Access-Control-Allow-Origin' $http_origin always;
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
            add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always;
            add_header 'Access-Control-Allow-Credentials' 'true' always;
            add_header 'Access-Control-Max-Age' 1728000 always;
            add_header 'Content-Type' 'text/plain; charset=utf-8' always;
            add_header 'Content-Length' 0 always;
            return 204;
    }
    if ($request_method = 'POST') {
            add_header 'Access-Control-Allow-Origin' $http_origin always;
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
            add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always;
            add_header 'Access-Control-Allow-Credentials' 'true' always;
            add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
    }
    if ($request_method = 'GET') {
            add_header 'Access-Control-Allow-Origin' $http_origin always;
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
            add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always;
            add_header 'Access-Control-Allow-Credentials' 'true' always;
            add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
    }

上方位于location 块,它将控制权传递给 uwsgi 套接字。 api1api2 的复制粘贴也是如此。

app1app2 正在向 api 发出请求,api 在响应其中一些请求时设置 cookie。

Cookie 设置如下:

response.set_cookie(
        key='some_cookie_name',
        value=some_token,
        max_age=current_app.config["JWT_EXP"],
        secure=True,
        httponly=True)

path 默认设置为'/'
domain 属性在响应中不存在, samesite 属性也不存在,
以上均根据this documentation.

如果我错了,请纠正我,但根据我的理解,当app1 请求api 资源(正在设置cookie)时,此cookie 绑定到app1.example.com 并且不应该出现在app2.example.com (反之亦然)。

我在 chrome 上观察到的行为是不同的。

app1 请求上设置cookie,然后在app2 请求上设置cookie(同名),会覆盖app1 上的cookie。 app2 子域不存在 cookie(使用 chrome 开发者工具检查)。

现在,当我更改第二个子域 (app2) 的 cookie 名称时,app2 上仍然不会出现 cookie,但是,现在可以在 app1 子域上看到具有不同名称的第二个 cookie。

看起来无论我做什么,所有 cookie 都设置在 app1 子域上。检查example.com 时也会出现这些cookie。

此外,当app2.example.comapi 发出请求时,它会发回app1 上可见的所有cookie。

这种行为正确吗?是因为在服务器端启用了 CORS 吗?如何区分 app1app2 之间的 cookie?

编辑:添加 cors 配置代码

【问题讨论】:

  • 你能告诉我你的 CORS 实现吗?在我看来,您遇到了 CORS 问题。
  • 我已将 nginx cors 配置添加到问题中。
  • 你能告诉我来自这个的响应头吗:curl -X OPTIONS 'api.example.com' -H "Origin: app1.example.com" -H "Access-Control-Request-Method: GET" -Iv -o /dev/null 看起来,你的 CORS 实现很好。
  • 这是一个输出。 Ofc 我已请求适当的资源作为适当的来源,在发布时将其更改为 app1pastebin.com/raw/nUuJAmZE
  • IN,我认为您的应用程序有问题,因为您的 CORS 实现是正确的(但不安全)。您收到了上述请求的有效标头。

标签: python google-chrome nginx cookies flask


【解决方案1】:

set-cookie 标头中的 cookie 域需要与请求它的主机相匹配。需要 CORS 和 cookie 标头。如果您没有在 Set-Cookie 上设置域,浏览器将假定所请求主机的 FQDN。如果您确实设置了域,则可以使用 domain=example.com 或类似名称在同一域上的站点之间共享 cookie。

虽然令人困惑,但可以在 FQDN 主机和主机所在的域上设置相同的 cookie 名称。一个会被发送到该域中的其他主机,两者将被发送到对同一 FQDN 的后续调用。

我希望您希望将 cookie 放在您的域上,而不是 FQDN 上。您应该能够重写 apt、app1 和 app2 返回的 Set-Cookie 标头,以便它们位于域上。如果可能,最好自行修复应用程序上的 cookie。

【讨论】:

  • 唉,如果我可以发表评论而不是回答,我会的。但是,在获得评论权之前,一个人有权回答。
猜你喜欢
  • 1970-01-01
  • 2011-04-10
  • 2020-12-10
  • 2020-05-24
  • 2023-04-10
  • 2017-10-06
  • 2021-05-02
  • 1970-01-01
  • 2011-07-12
相关资源
最近更新 更多