Как предотвратить множественный вход в Django - PullRequest
0 голосов
/ 13 июня 2018

Я пишу систему пользователя, которая не может войти одновременно.Если учетная запись в состоянии входа в систему где-то, и кто-то входит в эту же учетную запись в другой позиции.Последний будет авторизован. А предыдущий выйдет из системы.Я использую модель с oneToOneField, связанной с моделью User, и сохраняю идентификаторы сессий этого пользователя.Код подобен приведенному ниже.

from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
from .myModels import JSONField

class Profile(models.Model):
    user = models.OneToOneField(User, models.CASCADE)
    sessionids = JSONField(null=True)


@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)

JSONField - это поле, которое использует textField для хранения строки JSON.Когда пользователь входит в систему, я иду, чтобы получить все идентификаторы сеанса этого пользователя и удалить все идентификаторы сеанса.Затем я добавляю текущий идентификатор сессии в профиль.Сделав это, я могу выйти из предыдущей позиции.код, как показано ниже.

def login(request):
    if request.method == "POST":
        if request.user.is_authenticated:
            return HttpResponse("the user session is authenticated.")

        username = request.POST.get('username', '')
        password = request.POST.get('password', '')

        user = auth.authenticate(username=username, password=password)

        if user is not None and user.is_active:
            auth.login(request, user)

            #remove cur user all sessions
            sessionidsToDelete = request.user.profile.sessionids
            if sessionidsToDelete != None:
                sessions = Session.objects.filter(session_key__in=sessionidsToDelete)
                for session in sessions:
                    session.delete()

            #add cur user sessions
            sessionidsToStore = user.profile.sessionids
            print("sessionidsToStore = ")
            print(sessionidsToStore)
            print("sessionidsToDelete = ")
            print(sessionidsToDelete)

            if sessionidsToStore== None:
                sessionidsToStore = []
            else:
                sessionidsToStore = list(set(sessionidsToStore) - set(sessionidsToDelete))
            print("sessionidsToStore = ")
            print(sessionidsToStore)
            sessionidsToStore.append(request.session.session_key)
            user.profile.sessionids = json.dumps(sessionidsToStore)
            user.profile.save()

            rotate_token(request)
            return HttpResponse("login sucessful")
        elif user.is_active == False:
            userNotActivedHttpresponse = HttpResponse()
            userNotActivedHttpresponse.status_code = 605
            userNotActivedHttpresponse.reason_phrase = "This user not active"
            return userNotActivedHttpresponse
        else:
            return HttpResponse("Please Input the correct username and password")
    else:
        return HttpResponseBadRequest("Please use POST to login")

Но я думаю, что-то случится.Когда два человека хотят войти в одну и ту же учетную запись одновременно.Например, два человека знают одну и ту же учетную запись.Они входят в систему одновременно.Может случиться, что B добавляет идентификатор сеанса B в профиль после того, как A удаляет все другие идентификаторы сеанса.В этой ситуации A и B все еще будут в состоянии входа в систему и не будут выходить из системы.Как я мог предотвратить эту проблему?

1 Ответ

0 голосов
/ 13 июня 2018

Я думаю, что вы все усложняете, сохраняя данные в UserProfile с и т. Д., А затем получаете сигналы, вы вводите много уровней, и на каждом уровне все может пойти не так.

Здесь нам в основном нужны две вещи: таблица, которая отображает User s в соответствующие настройкиМы можем реализовать это с моделью UserSession:

# models.py

from django.conf import settings
from django.db import models
from django.contrib.sessions.models import Session

class UserSession(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    session = models.OneToOneField(Session, on_delete=models.CASCADE)

Таким образом, объект UserSession создает связь между User и Session с.Теперь мы можем реализовать ловушку входа : сигнал, который срабатывает в случае входа пользователя в систему. В этом случае мы выполняем две вещи:

  1. мы удаляем все Session s(и соответствующие UserSession s) из User, которые являются активными;и
  2. мы создаем новый Session и соответствующий UserSession, который мы можем удалить позже.Как:
from django.contrib.auth import <b>user_logged_in</b>
from django.dispatch.dispatcher import receiver

<b>@receiver(user_logged_in)</b>
def remove_other_sessions(sender, user, request, **kwargs):
    # remove other sessions
    Session.objects.filter(usersession__user=user).delete()

    # save current session
    request.session.save()

    # create a link from the user to the current session (for later removal)
    UserSession.objects.get_or_create(
        user=user,
        session=Session.objects.get(pk=request.session.session_key)
    )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...