Cookie冲突:在Django和Javascript中是否可以区分父域和子域cookie?
Cookie collision: is it possible to distinguish between parent domain and subdomain cookies in Django and Javascript?
我在一个域中构建了一堆 Django 网站:
- example.com
- 站点 1.example.com
- site2.example.com
- site3.example.com
它们应该完全独立 — 由不同的人用于不同的目的。
然而,由 example.com 设置的 cookie 被 Django 赋予优先权,而值由 site1.example.com, site2.example.com 等如果父域设置了同名的 cookie 将被忽略.
工作原理:
加载第一个页面时,它会设置一个 cookie,以便服务器知道在下一个请求时发送计算机页面或移动页面。
Django 程序根据 cookie 值构建正确的版本。
当 site1.example.com 加载时,它会设置一个 cookie,要求提供移动版本。但是随后 Django 程序看到 example.com 设置的值并且 忽略了正确的 cookie.
所以,我需要一种方法来执行以下操作之一:
- 防止 site1.example.com读取example.com
的cookie
- 在 Django 中区分 与 cookie 关联的域,因此我可以判断该值是错误的
- 找到一种在 Javascript 中设置父域 cookie 的方法,使其 无法访问 子域(我没有使用 www)
如果找不到优雅的解决方案,我可能最终会更改 cookie 名称以随域名变化。
我知道我可以使用 会话框架,但除了这个特殊问题外,一切都很好。我真的很想避免修改我现有的系统,但如果必须的话,我显然会这样做。
[更新]这里是cookie设置函数:
function setCookie(cname, cvalue, exdays) {
var domain = window.location.hostname;
if (exdays > 7) exdays = 7; // max in Safari
var d = new Date();
d.setTime(d.getTime() + (exdays*24*60*60*1000));
var name = cname + '=' + cvalue + '; ';
var expy = 'expires=' + d.toUTCString(); + '; ';
var domn = '; domain=' + domain + '; ';
var path = 'path=/; ';
var secu = 'samesite=lax; secure;';
var complete = name + expy + domn + path + secu;
document.cookie = complete;
}
作为临时修复,我在 setCookie 函数中添加了一些代码:
var domain = window.location.hostname;
deleteParentCookieIfNecessary(name, domain);
deleteParentCookieIfNecessary 包含:
function deleteParentCookieIfNecessary(name, domain){
var parts = domain.split('.');
if (parts.length > 2){ // on subdomain
var domain = parts.slice(-2).join('.');
document.cookie = cname + '=;domain=.' + domain + ';path=/;max-age=0';
}
}
结果是 设置 cookie 时,如果 url 是子域,则 parent-domain 的 cookie同名会被自动删除
既然你说网站应该是完全独立的,那么你提出的第三个解决方案似乎是最明智的。您不应以子域可以访问的方式设置 cookie。目前您正在 cookie 中指定域,您应该跳过域,这意味着 cookie 只会针对当前域发送(至少在现代浏览器中,IE 不遵循此规范)。如果在 cookie 中指定了域,则意味着该 cookie 也将用于子域。
如RFC 6265 - section 4.1.2.3所述:
If the server omits the Domain attribute, the user agent will return
the cookie only to the origin server.
因此您的 cookie 设置函数应该如下所示:
function setCookie(cname, cvalue, exdays) {
// Domain should not be set unless cookie needs to be accessed by subdomains
// var domain = window.location.hostname;
if (exdays > 7) exdays = 7; // max in Safari
var d = new Date();
d.setTime(d.getTime() + (exdays*24*60*60*1000));
var name = cname + '=' + cvalue + '; ';
var expy = 'expires=' + d.toUTCString(); + '; ';
// Domain should not be set unless cookie needs to be accessed by subdomains
// var domn = '; domain=' + domain + '; ';
var path = 'path=/; ';
var secu = 'samesite=lax; secure;';
var complete = name + expy + path + secu;
document.cookie = complete;
}
我在一个域中构建了一堆 Django 网站:
- example.com
- 站点 1.example.com
- site2.example.com
- site3.example.com
它们应该完全独立 — 由不同的人用于不同的目的。
然而,由 example.com 设置的 cookie 被 Django 赋予优先权,而值由 site1.example.com, site2.example.com 等如果父域设置了同名的 cookie 将被忽略.
工作原理:
加载第一个页面时,它会设置一个 cookie,以便服务器知道在下一个请求时发送计算机页面或移动页面。
Django 程序根据 cookie 值构建正确的版本。
当 site1.example.com 加载时,它会设置一个 cookie,要求提供移动版本。但是随后 Django 程序看到 example.com 设置的值并且 忽略了正确的 cookie.
所以,我需要一种方法来执行以下操作之一:
- 防止 site1.example.com读取example.com 的cookie
- 在 Django 中区分 与 cookie 关联的域,因此我可以判断该值是错误的
- 找到一种在 Javascript 中设置父域 cookie 的方法,使其 无法访问 子域(我没有使用 www)
如果找不到优雅的解决方案,我可能最终会更改 cookie 名称以随域名变化。
我知道我可以使用 会话框架,但除了这个特殊问题外,一切都很好。我真的很想避免修改我现有的系统,但如果必须的话,我显然会这样做。
[更新]这里是cookie设置函数:
function setCookie(cname, cvalue, exdays) {
var domain = window.location.hostname;
if (exdays > 7) exdays = 7; // max in Safari
var d = new Date();
d.setTime(d.getTime() + (exdays*24*60*60*1000));
var name = cname + '=' + cvalue + '; ';
var expy = 'expires=' + d.toUTCString(); + '; ';
var domn = '; domain=' + domain + '; ';
var path = 'path=/; ';
var secu = 'samesite=lax; secure;';
var complete = name + expy + domn + path + secu;
document.cookie = complete;
}
作为临时修复,我在 setCookie 函数中添加了一些代码:
var domain = window.location.hostname;
deleteParentCookieIfNecessary(name, domain);
deleteParentCookieIfNecessary 包含:
function deleteParentCookieIfNecessary(name, domain){
var parts = domain.split('.');
if (parts.length > 2){ // on subdomain
var domain = parts.slice(-2).join('.');
document.cookie = cname + '=;domain=.' + domain + ';path=/;max-age=0';
}
}
结果是 设置 cookie 时,如果 url 是子域,则 parent-domain 的 cookie同名会被自动删除
既然你说网站应该是完全独立的,那么你提出的第三个解决方案似乎是最明智的。您不应以子域可以访问的方式设置 cookie。目前您正在 cookie 中指定域,您应该跳过域,这意味着 cookie 只会针对当前域发送(至少在现代浏览器中,IE 不遵循此规范)。如果在 cookie 中指定了域,则意味着该 cookie 也将用于子域。
如RFC 6265 - section 4.1.2.3所述:
If the server omits the Domain attribute, the user agent will return the cookie only to the origin server.
因此您的 cookie 设置函数应该如下所示:
function setCookie(cname, cvalue, exdays) {
// Domain should not be set unless cookie needs to be accessed by subdomains
// var domain = window.location.hostname;
if (exdays > 7) exdays = 7; // max in Safari
var d = new Date();
d.setTime(d.getTime() + (exdays*24*60*60*1000));
var name = cname + '=' + cvalue + '; ';
var expy = 'expires=' + d.toUTCString(); + '; ';
// Domain should not be set unless cookie needs to be accessed by subdomains
// var domn = '; domain=' + domain + '; ';
var path = 'path=/; ';
var secu = 'samesite=lax; secure;';
var complete = name + expy + path + secu;
document.cookie = complete;
}