为什么Chrome在错误的子域上设置Cookie?

时间:2019-03-04 12:59:37

标签: python google-chrome nginx cookies flask

我有以下子域:

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

我正在使用nginx作为Web服务器来服务所有这些服务器。 api.example.com是我正在开发的python烧瓶应用程序。 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,复制粘贴相同。

app1app2api发出请求,而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,但是,{ {1}}子域。

无论我做什么,所有cookie都设置在app1子域上。检查app1时,这些cookie也存在。

此外,当example.comapp2.example.com发出请求时,它会发回在api上可见的所有cookie。

此行为正确吗?是否由于服务器端启用了CORS?如何在app1app1之间分隔cookie?

编辑:添加了cors配置代码

1 个答案:

答案 0 :(得分:0)

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

有可能在FQDN主机和该主机所在的域上设置相同的cookie名称,尽管会造成混淆。一个主机将被发送到该域中的其他主机,而两者将被发送到对同一FQDN的后续呼叫。

我希望您希望在您的域而不是FQDN上使用cookie。您应该能够重写apt,app1和app2返回的Set-Cookie标头,以便它们位于域中。如果可能,最好将Cookie固定在应用程序本身上。