0

I know this is a possible duplicate post, I found a solution for this, but those posts are from older versions of Django and I can't get the new syntaxis. Could someone give me a tip please?

I'm trying to prevent users to use the same account simultaneously. So when someone log in an account, if the user and pass are ok, I'm iterating the django_session table in order to find if theres any other session with the same account, if yes, close this session and start the last one.

After auth.authenticate(blah blah):

 if user is not None: # Checks if there's any other active session with the same account for session in Session.objects.filter(session_key=request.session.session_key): # //aq data = session.get_decoded() print(data.get('_auth_user_id', None)) if data.get('_auth_user_id', None) == str(user.id): session.delete() 

But something is not working with this syntaxis. I can't get the session user's ID. When a user logs in I'm using request.session['logueado'] = user.id and auth.login(request, user).

This should be like a "last to log in wins" system.

EDIT: Whole code:

def login(request): if 'logged' in request.session: return redirect(main) if request.method == "GET": form = LoginForm return render(request, "login.html", {"form": form}) if request.method == "POST": print('POST method.') form = LoginForm(request.POST) if form.is_valid(): print('Valid form.') user_name = form.cleaned_data.get('username') user_pass = form.cleaned_data.get('password') user = auth.authenticate(username=user_name, password=user_pass) if user is not None: for session in Session.objects.filter(session_key=request.session.session_key): print('Hello') data = session.get_decoded() if data.get('_auth_user_id', None) == request.session.session_key: print('Same account in more than 1 session.') session.delete() #------------------------------------------------------------------ request.session['logged'] = user.id print(request.session['logged']) auth.login(request, user) request.session.set_expiry(0) # return redirect(main) else: return render(request, "loginError.html", {"form": form}) 

EDIT: Definitive solution: (Thank you Daniel Roseman!)

user = auth.authenticate(username=user_name, password=user_pass) if user is not None: # Checks if there's another session with the same acc Sessions = Session.objects.all() for row in Sessions: print(row.get_decoded().get('_auth_user_id')) print(user.id) if str(row.get_decoded().get("_auth_user_id")) == str(user.id): print('Same sessions') row.delete() request.session['logged'] = user.id 
8
  • @ManzurulHoqueRumi it is simply not deleting the duplicate session (older). It's not preventing anything. Both sessions can be at the same time Commented Feb 13, 2019 at 11:50
  • I don't get what you're saying. I'm loging in with the same account at it doesn't avoid it. Commented Feb 13, 2019 at 12:16
  • Nothing in any of this will have changed syntax between versions of Django. Commented Feb 13, 2019 at 12:19
  • My for loop is wrong, it is not iterating Commented Feb 13, 2019 at 12:21
  • Do you mean it's not executing at all, or it's only executing once? Commented Feb 13, 2019 at 12:25

2 Answers 2

1

Your code is based on all sorts of false assumptions.

Session keys don't in any way map to login IDs. And they are unique: each client will have a different key, even if they're logged in as the same user. What's more, the session is explicitly flushed when a user logs in, so they will get a new key.

In other words, the only way to do something like this would be to iterate over all sessions in the database, decode them, and check if their _auth_user_id item is equal to the user ID.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you Daniel, you're pointing me to the right direction. I editted my post in order to show how I figured this, I can't make it work yet though. If you want to check it... I would appreciate it
What exactly goes wrong? One thing I can see is that you haven't actually logged the user in yet, so request.user.id is None; you should compare against just user.id. Note also that this is likely to get fairly expensive once you have a lot of users.
0

As Daniel Roseman answered, you can iterate over all sessions in DB, decode all of them, and delete those you want. But it's slow, particularly if your site has high traffic and there are lots of sessions.

If you need a faster solution, you can use a session backend that lets you query and get the sessions of a specific user. In these session backends, Session has a foreign key to User, so you don't need to iterate over all session objects:

Using these backends, deleting all sessions of a user can be done in a single line of code:

user.session_set.all().delete() 

Disclaimer: I am the author of django-qsessions.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.