Django总共只允许一个用户会话 [英] Django allow only one user session in total

查看:68
本文介绍了Django总共只允许一个用户会话的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在尝试对我的应用程序实施一项策略,一次只允许一个用户会话,如果用户尝试从另一台设备登录,则旧会话将被终止.

I currently try to implement a policy to my application that only one user session at a time is allowed, if a user trys to log-in from another device the old sessions gets killed.

但是对于某些人来说,我得到以下错误,而我自己也找不到错误:(:

But for some resone i get the following error and i can't find the mistake myself :( :

位于/User处的RelatedObjectDoesNotExist没有日志用户.

RelatedObjectDoesNotExist at / User has no logged_in_user.

我的项目包含两个应用程序,即实际应用程序和一个帐户"应用程序,其中包含此处显示的所有信息.

My project contains two apps, the actually app and a "accounts" app that contains all informations shown here.

signals.py

signals.py

# Signals that fires when a user logs in and logs out

from django.contrib.auth import user_logged_in, user_logged_out
from django.dispatch import receiver
from .models import LoggedInUser

@receiver(user_logged_in)
def on_user_logged_in(sender, request, **kwargs):
    LoggedInUser.objects.get_or_create(user=kwargs.get('user'))


@receiver(user_logged_out)
def on_user_logged_out(sender, **kwargs):
    LoggedInUser.objects.filter(user=kwargs.get('user')).delete()

models.py

models.py

# Model to store the list of logged in users
class LoggedInUser(models.Model):
    user = models.OneToOneField(User, related_name='logged_in_user', on_delete=models.CASCADE)
    session_key = models.CharField(max_length=32, null=True, blank=True)

    def __str__(self):
        return self.user

我的用户模型与此代码段位于同一位置

my User Model is at the same at the same location as this sippet

middleware.py

middleware.py

#Session model stores the session data
from django.contrib.sessions.models import Session
from .models import LoggedInUser

class OneSessionPerUserMiddleware:
    # Called only once when the web server starts
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        # Code to be executed for each request before
        # the view (and later middleware) are called.
        if request.user.is_authenticated:
            stored_session_key = request.user.logged_in_user.session_key

            # if there is a stored_session_key in the database and it is
            # different from the current session, delete the stored_session_key
            # session_key with from the Session table
            if stored_session_key and stored_session_key != request.session.session_key:
                Session.objects.get(session_key=stored_session_key).delete()

            request.user.logged_in_user.session_key = request.session.session_key
            request.user.logged_in_user.save()

        response = self.get_response(request)

        # This is where you add any extra code to be executed for each request/response after
        # the view is called.

        return response

更新:

我的middleware.py文件现在看起来像:

my middleware.py file now looks like:

# Session model stores the session data
from django.contrib.sessions.models import Session
from .models import LoggedInUser


class OneSessionPerUserMiddleware:
    # Called only once when the web server starts
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        # Code to be executed for each request before
        # the view (and later middleware) are called.
        if request.user.is_authenticated:
            session_key = request.session.session_key

            # if there is a stored_session_key  in our database and it is
            # different from the current session, delete the stored_session_key
            # session_key with from the Session table
            try:
                logged_in_user = request.user.logged_in_user
                stored_session_key = logged_in_user.session_key
                # stored_session_key exists so delete it if it's different
                if stored_session_key != session_key:
                    Session.objects.filter(session_key=stored_session_key).delete()
                logged_in_user.session_key = session_key
                logged_in_user.save()
            except LoggedInUser.DoesNotExist:
                LoggedInUser.objects.create(user=request.user, session_key=session_key)

        response = self.get_response(request)

        return response

这似乎工作正常,但是如果我从两个不同的浏览器中以同一用户身份登录,我仍然能够做到这一点,而且我仍然会获得两个不同的会话密钥,并且会话保持打开状态.

which seems to work fine but if i log in with the same user from two different browsers, I'm still able to do this and i still get two different sessions keys and the session stays open.

如果我从两台不同的计算机上登录时检查数据库以同一用户身份访问该应用程序,则LoggedInUser表上保存的会话密钥会简单更改,但该应用程序的行为并不像至少已撤销了该密钥最古老的会话!?

If i check at the database while logged in from two diffrent computers to access the application as the same user, the saved session key at the LoggedInUser table simple changes but the application does not act like the key has been revoked from at least the oldest session!?

推荐答案

实际上错误在这里发生,

Actually the error occurs here,

stored_session_key = request.user.logged_in_user.session_key

即.登录用户的相关 logged_in_user ( LoggedInUser 对象)不存在.因此,您必须创建一个新的.

ie. the related logged_in_user (LoggedInUser object) doesn't exists for the logged in user. So you have to create a a new one.

session_key = request.session.session_key

try:
    logged_in_user = request.user.logged_in_user
    stored_session_key = logged_in_user.session_key
    # stored_session_key exists so delete it if it's different
    if stored_session_key != session_key:
        Session.objects.filter(session_key=stored_session_key).delete()
    logged_in_user.session_key = session_key
    logged_in_user.save()
except LoggedInUser.DoesNotExist:
    LoggedInUser.objects.create(user=request.user, session_key=session_key)

这篇关于Django总共只允许一个用户会话的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆