Django 总共只允许一个用户会话
Django allow only one user session in total
我目前尝试对我的应用程序实施一项政策,即一次只允许一个用户会话,如果用户尝试从另一台设备登录,旧会话将被终止。
但是对于一些resone,我得到以下错误,我自己找不到错误:( :
RelatedObjectDoesNotExist at / User has no logged_in_user.
我的项目包含两个应用程序,实际应用程序和一个包含此处显示的所有信息的 "accounts" 应用程序。
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
# 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
我的用户模型与此 sippet 位于同一位置
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 文件现在看起来像:
# 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
这似乎工作正常,但如果我从两个不同的浏览器使用同一个用户登录,我仍然能够这样做并且我仍然获得两个不同的会话密钥并且会话保持打开状态。
如果我在从两台不同的计算机登录时检查数据库以作为同一用户访问应用程序,则保存在 LoggedInUser table 的会话密钥会发生简单的更改,但应用程序不会像密钥一样运行已从至少最旧的会话中撤销!?
其实错误就出现在这里,
stored_session_key = request.user.logged_in_user.session_key
即。登录用户不存在相关 logged_in_user
(LoggedInUser
对象)。所以你必须创建一个新的。
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)
这个有效并回答了您的问题。:
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
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 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()
except LoggedInUser.DoesNotExist:
LoggedInUser.objects.create(user=request.user, session_key=session_key)
stored_session_key = request.user.logged_in_user.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
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.
# For this tutorial, we're not adding any code so we just return the response
return response
我目前尝试对我的应用程序实施一项政策,即一次只允许一个用户会话,如果用户尝试从另一台设备登录,旧会话将被终止。
但是对于一些resone,我得到以下错误,我自己找不到错误:( :
RelatedObjectDoesNotExist at / User has no logged_in_user.
我的项目包含两个应用程序,实际应用程序和一个包含此处显示的所有信息的 "accounts" 应用程序。
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
# 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
我的用户模型与此 sippet 位于同一位置
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 文件现在看起来像:
# 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
这似乎工作正常,但如果我从两个不同的浏览器使用同一个用户登录,我仍然能够这样做并且我仍然获得两个不同的会话密钥并且会话保持打开状态。
如果我在从两台不同的计算机登录时检查数据库以作为同一用户访问应用程序,则保存在 LoggedInUser table 的会话密钥会发生简单的更改,但应用程序不会像密钥一样运行已从至少最旧的会话中撤销!?
其实错误就出现在这里,
stored_session_key = request.user.logged_in_user.session_key
即。登录用户不存在相关 logged_in_user
(LoggedInUser
对象)。所以你必须创建一个新的。
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)
这个有效并回答了您的问题。:
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
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 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()
except LoggedInUser.DoesNotExist:
LoggedInUser.objects.create(user=request.user, session_key=session_key)
stored_session_key = request.user.logged_in_user.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
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.
# For this tutorial, we're not adding any code so we just return the response
return response