Welcome to my first tutorial on this platform. In this one i'm going to show you how to prevent a user account from having multiple sessions at the...
For further actions, you may consider blocking this person and/or reporting abuse
Thanks
Nice! BTW in a real world app instead of logging out the other user(s) you would probably tell them "Hey, stop streaming 50 videos :D".
Having more than one session could be accidental: I'm logged in on the phone and on the computer and I would hate to be automatically logged out on the other device.
That's very true.
Thanks for your comment on my first post here. I really appreciate.
My approach could be useful when the partner to a cheat in a relationship picks up the phone and the cheat is logged in on my tinder-like app. The cheater could quickly rush to his/her computer and log out. (LIFE SAVER SCENARIO)
The idea was just to show how to create a custom middleware. Like i stated in while concluding, this might not be the best approach.
I am getting this error when I uploaded the site to pythonanywhere (It was working fine locally)
Environment:
Request Method: GET
Request URL: careerabacusgallery.pythonanywhere...
Django Version: 4.0.1
Python Version: 3.9.5
Installed Applications:
['onlinetest.apps.OnlinetestConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'onlinetest.middleware.OneSessionPerUserMiddleware']
Traceback (most recent call last):
File "/home/careerabacusgallery/.virtualenvs/test/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/home/careerabacusgallery/statelevel/onlinetest/middleware.py", line 19, in call
Session.objects.get(session_key=stored_session_key).delete()
File "/home/careerabacusgallery/.virtualenvs/test/lib/python3.9/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/home/careerabacusgallery/.virtualenvs/test/lib/python3.9/site-packages/django/db/models/query.py", line 439, in get
raise self.model.DoesNotExist(
Exception Type: DoesNotExist at /lgi
Exception Value: Session matching query does not exist.
my signals.py
from django.contrib.auth import user_logged_in, user_logged_out
from django.dispatch import receiver
from .models import User, LoggedInUser
from django.contrib.sessions.models import Session
from accounts.models import User, LoggedInUser, UserSession
@receiver(user_logged_in)
def when_user_logs_in(sender, request, **kwargs):
print('user_logs_signal is called')
LoggedInUser.objects.get_or_create(user=kwargs.get('user'))
@receiver(user_logged_out)
def when_user_logs_out(sender, request, **kwargs):
print('user logs out signal iscalled')
LoggedInUser.objects.get_or_create(user=kwargs.get('user')).delete()
my models.py
class LoggedInUser(models.Model):
user = models.OneToOneField(User, related_name='logged_in_user', on_delete =models.CASCADE, null=True, blank=True)
session_key = models.CharField(max_length=32, null=True, blank=True)
my apps.py
from django.apps import AppConfig
class AccountsConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "accounts"
i have added the app in settings.py but my signals are not working please help
this one works for me:
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
class OneSessionPerUserMiddleware:
Called only once when the web server starts
def init(self, get_response):
self.get_response = get_response
How do you implement this code? Could you spell out where this code should reside? Which directories, files etc ...?
Thanks for the tutorial,
Is there any way to enforce this behavior without user interaction to website?
For instance in livestream scenarios if a user logins with credentials from device A and shares credentials to device B, if user never interacts with device A both could watch the livestream
Good question.
The approach used here would log out the user whenever he/she makes any request.
For your streaming example, something like Django channels would need to be used.
So you can take the logic used in my middleware and integrate it with Django channels.
So immediately the user logs in from another device, you send the logout event to the first device and maybe redirect to the login page.
Django channels supports the standard Django authentication out of the box.
Hi Emmanuel,
thanks a lot for this tutorial. I have implemented it on one of my project and it works except in twp situations:
The second issue is due to Django behavior when updating password that update session_key. So when we want to delete, previous session_key no more exist
I just add a condition to check for session_key exsit before deleting and it seems to works but need to investigate more in detail.
if stored_session_key and stored_session_key != request.session.session_key:
if Session.objects.filter(session_key=stored_session_key).exists():
Session.objects.get(session_key=stored_session_key).delete()
Do you had the same issues? How do you solve it?
request.user.is_authenticated always coming as false for me so i am not going inside that middleware what should i do
It means you're not logged in.
To confirm if you're loggedn in print out
request.user
.If it returns AnonymousUser then it means you're not logged in correctly.
Yes that was my mistake i solved , please help me in my last error. Error is that my signals are not firing i had added the signals as mentioned, also i imported signals in apps.py and added my app in settings.py but they are not working please help me in this issue
Gracias Excelente. me ayudo bastante ✔😃👌
Thank you. I'm glad it was helpful to you. Gracias amigo
Is there a specific reason why you do this check with middleware (every request)? Why don't you just check once when the user logs in?
Did that for demonstration purpose just to show how middlewares work and how you could use them.
You could just trigger the check in a signal when the user logs in and it would still give you the same result.
I stated in the conclusion that this might not be the perfect solution for such feature.
Thanks for your comment and i'm glad you spotted that.
You're really smart.
All the best
After log in, I get error 'User' object has no attribute 'user_session'. How to fix this error?
Could you provide the code where this error points to.
This could be caused by different reasons.
Are you sure you're importing the
User
model from the right path?Finally could you show where you used
user_session
in your code.Hi! I got this problem when i try to change the user thats is try to log in:
DoesNotExist at /
Session matching query does not exist.
How can I fix this error?
Hi. I replied on the YouTube video today.
I got this error 'CustomUser' object has no attribute 'logged_in_user' full trace back dpaste.com/16N37EM
Hi. I replied to your comment and YouTube but guess you deleted it.
Here you go:
The code snippet you posted has expired but from your error message, it shows you created a CustomUser model and it has no reverse relation with the LoggedInUser model.
Make sure you set the CustomUser model as the OneToOneField for user in your LoggedInUser model.
That could be the possible cause for this because i used settings.AUTH_USER_MODEL for mine. Or you could just set the AUTH_USER_MODEL to your CustomUser model in your settings.py file and your code should work as expected.
Thanks For reply,
Now Its Working!!!
thanks for help
You're welcome.
Can I see views.py file, please?
Thanks a lot!
I dont have it anymore.
It should work for the default login view.
This is the gist i created: gist.github.com/fleepgeek/92b01d31...
Does this work with JWT in django rest framework?
It should work as long as whatever library you're using is using Sessions