Django,具有多个域的 SESSION_COOKIE_DOMAIN

发布于 2024-08-18 23:51:31 字数 136 浏览 9 评论 0原文

在 Django 中,我将 SESSION_COOKIE_DOMAIN 设置为我的域名。但我实际上想用两个不同的域名运行同一个网站。

设置 SESSION_COOKIE_DOMAIN 后,只有指定的域允许用户登录。是否可以同时允许两个域登录?

In Django, I have SESSION_COOKIE_DOMAIN set to my domain name. But I would actually like to run the same site with two different domain names.

With SESSION_COOKIE_DOMAIN set, only the named domain allows the user to login. Is it possible to allow both domains to login?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

仅冇旳回忆 2024-08-25 23:51:31

如果您将会话 cookie 域设置为以“.”开头字符它将让您处理通配符子域并在多个子域之间共享会话 cookie(登录会话)。

In settings.py:
SESSION_COOKIE_DOMAIN=".stackoverflow.com"

上面的代码将允许在 user1.stackoverflow.com 和 user2.stackoverflow.com 之间共享 cookie。

如果您确实希望同一站点的 url 不同,您是否希望同一用户在一次登录会话中在两个站点之间切换?或者您只是想让两个不同的用户从两个不同的网址(不是子域?)登录到该网站

If you set your session cookie domain to start with a "." character it will let you handle wildcard sub-domains and share a session cookie (login session) across multiple subdomains.

In settings.py:
SESSION_COOKIE_DOMAIN=".stackoverflow.com"

The above would allow a cookie to be shared across user1.stackoverflow.com and user2.stackoverflow.com.

If you really do want the url's to be different for the same site, would you want the same user to switch between the two sites on one login session? Or do you just want the ability to have two different users login to the site from two different url's (that are not sub-domains?)

仄言 2024-08-25 23:51:31

标准SessionMiddleware仅支持1个SESSION_COOKIE_DOMAIN,仅适用于一个域及其子域。

这是一个变体,它将根据请求主机动态设置 cookie 域。要使用它,只需更新您的 MIDDLEWARE_CLASSES 以使用这一 SessionHostDomainMiddleware,而不是 SessionMiddleware。这更好吗,@jcdyer 和@interstar?

import time

from django.conf import settings
from django.utils.cache import patch_vary_headers
from django.utils.http import cookie_date
from django.contrib.sessions.middleware import SessionMiddleware

class SessionHostDomainMiddleware(SessionMiddleware):
    def process_response(self, request, response):
        """
        If request.session was modified, or if the configuration is to save the
        session every time, save the changes and set a session cookie.
        """
        try:
            accessed = request.session.accessed
            modified = request.session.modified
        except AttributeError:
            pass
        else:
            if accessed:
                patch_vary_headers(response, ('Cookie',))
            if modified or settings.SESSION_SAVE_EVERY_REQUEST:
                if request.session.get_expire_at_browser_close():
                    max_age = None
                    expires = None
                else:
                    max_age = request.session.get_expiry_age()
                    expires_time = time.time() + max_age
                    expires = cookie_date(expires_time)
                # Save the session data and refresh the client cookie.
                # Skip session save for 500 responses, refs #3881.
                if response.status_code != 500:
                    request.session.save()
                    host = request.get_host().split(':')[0]
                    response.set_cookie(settings.SESSION_COOKIE_NAME,
                            request.session.session_key, max_age=max_age,
                            expires=expires, domain=host,
                            path=settings.SESSION_COOKIE_PATH,
                            secure=settings.SESSION_COOKIE_SECURE or None,
                            httponly=settings.SESSION_COOKIE_HTTPONLY or None)
        return response

The standard SessionMiddleware only supports one SESSION_COOKIE_DOMAIN, which is only good for one domain and subdomains thereof.

Here's a variation that will set the cookie domain dynamically based on the request host. To use it, just update your MIDDLEWARE_CLASSES to use this one SessionHostDomainMiddleware, instead of SessionMiddleware. This better, @jcdyer and @interstar?

import time

from django.conf import settings
from django.utils.cache import patch_vary_headers
from django.utils.http import cookie_date
from django.contrib.sessions.middleware import SessionMiddleware

class SessionHostDomainMiddleware(SessionMiddleware):
    def process_response(self, request, response):
        """
        If request.session was modified, or if the configuration is to save the
        session every time, save the changes and set a session cookie.
        """
        try:
            accessed = request.session.accessed
            modified = request.session.modified
        except AttributeError:
            pass
        else:
            if accessed:
                patch_vary_headers(response, ('Cookie',))
            if modified or settings.SESSION_SAVE_EVERY_REQUEST:
                if request.session.get_expire_at_browser_close():
                    max_age = None
                    expires = None
                else:
                    max_age = request.session.get_expiry_age()
                    expires_time = time.time() + max_age
                    expires = cookie_date(expires_time)
                # Save the session data and refresh the client cookie.
                # Skip session save for 500 responses, refs #3881.
                if response.status_code != 500:
                    request.session.save()
                    host = request.get_host().split(':')[0]
                    response.set_cookie(settings.SESSION_COOKIE_NAME,
                            request.session.session_key, max_age=max_age,
                            expires=expires, domain=host,
                            path=settings.SESSION_COOKIE_PATH,
                            secure=settings.SESSION_COOKIE_SECURE or None,
                            httponly=settings.SESSION_COOKIE_HTTPONLY or None)
        return response
爱她像谁 2024-08-25 23:51:31

我想这就是你正在寻找的东西,我花了几个小时才找到它

https://bitbucket.org /uysrc/django-dynamicsites

I think this is what you are looking for, I took me hours to find it out

https://bitbucket.org/uysrc/django-dynamicsites

昇り龍 2024-08-25 23:51:31

这是一个简单的 DynamicDomain 解决方案,适用于 Django 3.x、4.x 和 5.x。

设置

添加您想要支持的域。始终以“.”开头。支持所有子域。该列表可确保安全。没有人可以将他们的域名指向您的 IP 地址并获取会话 cookie!

SESSION_COOKIE_DOMAIN_DYNAMIC = ['.example.com', '.newexample.org']

在中间件中,添加新的中间件上面 SessionMiddleware

    MIDDLEWARE = [
        ...
        'django_mods.middleware.SessionMiddlewareDynamicDomain',
        'django.contrib.sessions.middleware.SessionMiddleware',
        ...

新会话中间件

创建新的中间件,负责根据传入请求正确设置 cookie 域。如果登录请求来自 abc.example.com,则 sessionid 的 cookie domain 将设置为 .example.com.同样,如果请求来自 abc.newexample.org,它将被设置为 .newexample.org

import logging

from django.conf import settings
from django.utils.deprecation import MiddlewareMixin


class SessionMiddlewareDynamicDomain(MiddlewareMixin):
    def __init__(self, get_response):
        super().__init__(get_response)

    def process_response(self, request, response):
        if settings.SESSION_COOKIE_NAME in response.cookies:
            try:
                domain_curr = response.cookies[settings.SESSION_COOKIE_NAME]['domain']

                request_domain = '.' + '.'.join(request.get_host().split(':')[0].split('.')[-2:])

                if request_domain in settings.SESSION_COOKIE_DOMAIN_DYNAMIC:
                    if domain_curr != request_domain:
                        response.cookies[settings.SESSION_COOKIE_NAME]['domain'] = request_domain
            except Exception as exc:
                logging.error(f'crash updating domain dynamically. Skipped. Error: {exc}')

        return response

Here's a simple DynamicDomain solution that works across Django 3.x, 4.x and 5.x.

Settings

Add the domains you want to support. Always start with a "." to support all subdomains. This list ensures security. No one can just point their domain to your IP address and get the session cookie delivered!

SESSION_COOKIE_DOMAIN_DYNAMIC = ['.example.com', '.newexample.org']

In middleware, add the new middleware above SessionMiddleware

    MIDDLEWARE = [
        ...
        'django_mods.middleware.SessionMiddlewareDynamicDomain',
        'django.contrib.sessions.middleware.SessionMiddleware',
        ...

New Session Middleware

Create the new middleware that takes care of setting cookie domain properly based on the incoming request. If request to login comes from abc.example.com the cookie domain for sessionid will be set to .example.com. Similarly, if request comes from abc.newexample.org it will be set to .newexample.org.

import logging

from django.conf import settings
from django.utils.deprecation import MiddlewareMixin


class SessionMiddlewareDynamicDomain(MiddlewareMixin):
    def __init__(self, get_response):
        super().__init__(get_response)

    def process_response(self, request, response):
        if settings.SESSION_COOKIE_NAME in response.cookies:
            try:
                domain_curr = response.cookies[settings.SESSION_COOKIE_NAME]['domain']

                request_domain = '.' + '.'.join(request.get_host().split(':')[0].split('.')[-2:])

                if request_domain in settings.SESSION_COOKIE_DOMAIN_DYNAMIC:
                    if domain_curr != request_domain:
                        response.cookies[settings.SESSION_COOKIE_NAME]['domain'] = request_domain
            except Exception as exc:
                logging.error(f'crash updating domain dynamically. Skipped. Error: {exc}')

        return response
萝莉病 2024-08-25 23:51:31

我正在使用 django 3.1.4,它对我有用。

创建一个像这样的中间件,我正在我的应用程序中创建utilities.middleware

class CrossDomainSessionMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        response = self.get_response(request)
        if response.cookies:
            host = request.get_host()
            # check if it's a different domain
            if host not in settings.SESSION_COOKIE_DOMAIN:
                domain = ".{domain}".format(domain=host)
                for cookie in response.cookies:
                    if 'domain' in response.cookies[cookie]:
                        response.cookies[cookie]['domain'] = domain
        return response

现在将此中间件放在settings.py内的SessionMiddleware上方

'utilities.middlware.CrossDomainSessionMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',

确保您的settings.py中有这两个变量

SESSION_COOKIE_DOMAIN = '.domain.com'
SESSION_COOKIE_NAME = 'domainsessionid'

I am using django 3.1.4, it worked for me.

Create a middleware like this, I am creating inside my app utilities.middleware

class CrossDomainSessionMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        response = self.get_response(request)
        if response.cookies:
            host = request.get_host()
            # check if it's a different domain
            if host not in settings.SESSION_COOKIE_DOMAIN:
                domain = ".{domain}".format(domain=host)
                for cookie in response.cookies:
                    if 'domain' in response.cookies[cookie]:
                        response.cookies[cookie]['domain'] = domain
        return response

Now place this middleware above SessionMiddleware inside settings.py

'utilities.middlware.CrossDomainSessionMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',

Make sure you have these two variable in your settings.py

SESSION_COOKIE_DOMAIN = '.domain.com'
SESSION_COOKIE_NAME = 'domainsessionid'
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文