Это интересный вопрос.Для этого должно быть много способов, первое, что приходит мне в голову, это использовать iframe
.В приведенном ниже примере проверяется Django 2.2
.
. В вашем settings.py
выставьте sessionid
на javascript.
SESSION_COOKIE_HTTPONLY = False
На ваш взгляд, обязательно поставьте xfram_options_exempt
или django не разрешит "вставлять" его из другого домена, здесь я использую шаблонное представление, поэтому вместо этого я помещаю декоратор в urls.py
.
from django.views.decorators.clickjacking import xframe_options_exempt
urlpatterns = [
path(
'other_domain/',
xframe_options_exempt(TemplateView.as_view(template_name='examplesite/otherdomain.html')),
name='other_domain',
)
# ...
]
domains
- это списокиз всех других доменов (не включая тот, на котором сейчас находится ваш пользователь), в вашем шаблоне выставьте их в теге <head>
.
<head>
{{ domains|json_script:"domains" }}
{{ other_domain_path|json_script:"other-domain-path"}}
</head>
это станет примерно так:
<script id="domains" type="application/json">["c222dbef.ngrok.io"] </script>
<script id="other-domain-path" type="application/json">"/other_domain/"</script>
Тогда в вашем javascript:
(function() {
function getCookie(cname) { //copied from w3schools
var name = cname + "=";
var decodedCookie = decodeURIComponent(document.cookie);
var ca = decodedCookie.split(";");
for (var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == " ") {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
}
}
return "";
}
function postSessionID(id) {
var domains = JSON.parse(document.getElementById("domains").textContent);
var path = JSON.parse(document.getElementById("other-domain-path").textContent);
domains.forEach(function(domain) {
var src = "https://" + domain + path;
var iframeEl = document.createElement("iframe");
iframeEl.setAttribute("class", "invisible");
iframeEl.setAttribute("src", src);
(function(id) { // this is an async call in a loop, create a closure here to protect "id"
iframeEl.addEventListener("load", function() {
this.contentWindow.postMessage(id, this.getAttribute("src"));
});
})(id);
document.body.appendChild(iframeEl);
});
}
function main() {
var sessionID = getCookie("sessionid");
if (!sessionID) {
return;
}
postSessionID(sessionID);
}
main();
})();
Идея вышеприведенного кода заключается в создании iframes для доменов друг друга, src iframes указывает на наш view
named "other_domain».После загрузки фреймов мы используем postMessage
для отправки им идентификатора сессии.
В examplesite/otherdomain.html
:
<head>
{{ domains|json_script:"domains" }}
{# we also need to expose all other domains #}
</head>
в вашем скрипте:
(function() {
function setCookie(cname, cvalue, exdays) {
var d = new Date();
d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
var expires = "expires=" + d.toUTCString();
document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
}
var domains = JSON.parse(document.getElementById("domains").textContent);
var trustedSources = domains.map(function(domain) {
return "https://" + domain;
});
window.addEventListener("message", function(e) {
if (!e.origin in trustedSources) {
return; // this prevents setting session id from other source
}
var sessionID = e.data;
// you can probably get your cookie expiry from your django view, so all of your cookie expires at the same time
setCookie("sessionid", sessionID, 365);
}, false);
})();
Теперь ваши пользователи могут входить и выходить из любого из ваших доменов, и у них будет один и тот же сеанс для всех ваших доменов.
Я публикую полный пример в моем github: https://github.com/rabbit-aaron/django-multisite-sign-in
Выполните настройку readme.md
.