简体   繁体   English

Set-Cookie 在 Chrome 中不起作用 - 有两个网站

[英]Set-Cookie is not working in Chrome - with two websites

I have a problem with Set-Cookie not working in Chrome (I didn't check other browsers).我遇到了Set-Cookie在 Chrome 中不起作用的问题(我没有检查其他浏览器)。 It worked in the past but it stopped working recently.它过去有效,但最近停止工作。 I have two websites with two domain names, and I need to set the cookie in both websites.我有两个网站有两个域名,我需要在两个网站中设置 cookie。 I'm calling a URL in each of the domain names to set the cookie.我在每个域名中调用一个 URL 来设置 cookie。 But it doesn't set the cookie on the other website (the website I'm not browsing now).但它不会在其他网站(我现在没有浏览的网站)上设置 cookie。

The users login or logout or sign up to one website, and I want them to login or logout from the other website too, automatically.用户登录或注销或注册一个网站,我希望他们也自动从另一个网站登录或注销。 Currently if they login or logout to one website, it doesn't affect the other website.目前,如果他们登录或注销一个网站,它不会影响另一个网站。

The Django view code is: Django 视图代码是:

@csrf_exempt
def set_session(request):
    """
    Cross-domain authentication.
    """
    response = HttpResponse('')
    origin = request.META.get('HTTP_ORIGIN')
    if isinstance(origin, bytes):
        origin = origin.decode()
    netloc = urlparse(origin).netloc
    if isinstance(netloc, bytes):
        netloc = netloc.decode()
    valid_origin = any(netloc.endswith('.' + site.domain) for site in Site.objects.all().order_by("pk"))
    if (not (valid_origin)):
        return response
    if (request.method == 'POST'):
        session_key = request.POST.get('key')
        SessionStore = import_module(django_settings.SESSION_ENGINE).SessionStore
        if ((session_key) and (SessionStore().exists(session_key))):
            # Set session cookie
            request.session = SessionStore(session_key)
            request.session.modified = True
        else:
            # Delete session cookie
            request.session.flush()
    response['Access-Control-Allow-Origin'] = origin
    response['Access-Control-Allow-Credentials'] = 'true'
    return response

And the JavaScript code is: JavaScript 代码是:

window.speedy = {};

window.speedy.setSession = function (domain, key) {
    $.ajax({
        url: '//' + domain + '/set-session/',
        method: 'post',
        data: {
            key: key
        },
        xhrFields: {
            withCredentials: true
        }
    });
};

Then there is a JavaScript code that calls this function twice:然后有一段 JavaScript 代码调用了这个函数两次:

speedy.setSession('speedy.net', 'session_key');
speedy.setSession('speedymatch.com', 'session_key');

Where 'session_key' is replaced by the session key of the user.其中'session_key'由用户的会话密钥替换。

Is there any solution to this problem?这个问题有什么解决办法吗? I think this is due to recent changes in Chrome.我认为这是由于 Chrome 最近的变化。

Update: We have a staging server where both the websites domains are subdomains of the same registered domain name.更新:我们有一个临时服务器,其中两个网站域都是相同注册域名的子域。 And there, Set-Cookie works fine.在那里, Set-Cookie工作正常。 But in the production websites, I think the other site's cookies are blocked by Chrome because the other site's domain is different from the domain the user is currently browsing.但是在生产网站中,我认为其他站点的 cookie 被 Chrome 阻止了,因为其他站点的域与用户当前浏览的域不同。

I checked and the cookies from the other website also don't work with Firefox and Dolphin.我检查过,来自其他网站的 cookie 也不适用于 Firefox 和 Dolphin。 It might be related to the upgrade to Django 2.1 which we upgraded recently.这可能与我们最近升级到 Django 2.1 的升级有关。

The same origin policy for cookies being triggered here;此处触发 cookie 的同源策略; from a domain you can set cookies for:您可以为以下域设置 cookie:

  • own domain自己的域名
  • parent domain (unless the parent domain is a (g)TLD)父域(除非父域是 (g)TLD)

So as the two domains in question do not share the parent-child relationship and the only common parent of them could be the TLD (assuming same TLD), you can't do this.因此,由于有问题的两个域不共享父子关系,并且它们唯一共同的父级可能是 TLD(假设相同的 TLD),您不能这样做。

From MDN doc :来自MDN 文档

Cookies use a separate definition of origins. Cookie 使用单独的来源定义。 A page can set a cookie for its own domain or any parent domain, as long as the parent domain is not a public suffix.页面可以为其自己的域或任何父域设置 cookie,只要父域不是公共后缀即可。 Firefox and Chrome use the Public Suffix List to determine if a domain is a public suffix. Firefox 和 Chrome 使用公共后缀列表来确定域是否为公共后缀。 Internet Explorer uses its own internal method to determine if a domain is a public suffix. Internet Explorer 使用其自己的内部方法来确定域是否是公共后缀。 The browser will make a cookie available to the given domain including any sub-domains, no matter which protocol (HTTP/HTTPS) or port is used.无论使用哪种协议 (HTTP/HTTPS) 或端口,浏览器都会向给定域(包括任何子域)提供 cookie。 When you set a cookie, you can limit its availability using the Domain, Path, Secure and Http-Only flags.当您设置 cookie 时,您可以使用域、路径、安全和 Http-Only 标志来限制其可用性。 When you read a cookie, you cannot see from where it was set.当您读取 cookie 时,您无法看到它的设置位置。 Even if you use only secure https connections, any cookie you see may have been set using an insecure connection.即使您只使用安全的 https 连接,您看到的任何 cookie 也可能是使用不安全的连接设置的。

Thanks to @aaron I found out the problem.感谢@aaron,我发现了这个问题。 This problem started only recently, after I upgraded Django to 2.1.这个问题是最近才开始的,在我将 Django 升级到 2.1 之后。 Django 2.1 introduced the SESSION_COOKIE_SAMESITE setting, which must be set to None for our websites to work properly with session cookies. Django 2.1 引入了SESSION_COOKIE_SAMESITE设置,必须将其设置为None才能使我们的网站与会话 cookie 正常工作。 On the other hand, CSRF_COOKIE_SAMESITE for our websites can be set to 'Strict' , since we use separate CSRF cookies for each website.另一方面,我们网站的CSRF_COOKIE_SAMESITE可以设置为'Strict' ,因为我们为每个网站使用单独的 CSRF cookie。 Therefore, I added the following lines to our base settings:因此,我在我们的基本设置中添加了以下几行:

SESSION_COOKIE_SECURE = True
SESSION_COOKIE_SAMESITE = None

CSRF_COOKIE_SECURE = True
CSRF_COOKIE_SAMESITE = 'Strict'

From those lines, only SESSION_COOKIE_SAMESITE = None is necessary to fix the problem I mentioned in this question.从这些行来看,只有SESSION_COOKIE_SAMESITE = None是解决我在这个问题中提到的问题所必需的。 I relied on the default setting of Django 2.1 to the value of SESSION_COOKIE_SAMESITE , which was not working for us in this case.我依赖 Django 2.1 的默认设置为SESSION_COOKIE_SAMESITE的值,在这种情况下对我们不起作用。

Currently the login and logout works in Chrome on my desktop and in one mobile phone.目前登录和注销在我的桌面和一部手机上的 Chrome 中工作。 But I checked another mobile phone I have, and there it doesn't work - the problem persists as it was before.但是我检查了我拥有的另一部手机,但它不起作用 - 问题仍然存在。 I'm not sure if this is due to a personal settings in this mobile phone or in the Chrome app?我不确定这是否是由于此手机或 Chrome 应用程序中的个人设置造成的? But login and logout to both websites simultaneously doesn't work there.但是同时登录和注销两个网站在那里不起作用。 If I login to one website, I'm still logged out from the other website, and vice versa.如果我登录到一个网站,我仍然从另一个网站注销,反之亦然。

Currently the login and logout works in Chrome.目前登录和注销在 Chrome 中工作。 The problem was cookies settings - check your settings at chrome://settings/cookies (desktop) or settings > site settings > cookies (mobile).问题在于 cookie 设置 - 在chrome://settings/cookies (桌面)或settings > site settings > cookies (移动)上检查您的设置。

(August 2020) Update: It is now required to use the following settings for Chrome. (2020 年 8 月)更新:现在需要为 Chrome 使用以下设置。 Please see this question and answer .请参阅问答

SESSION_COOKIE_SECURE = True
SESSION_COOKIE_SAMESITE = 'None'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM