is_authenticated возвращает True для вышедшего из системы пользователя

Я пишу серверное приложение, используя Django, Django REST framework, Django-rest-auth и Django-allauth. У меня есть метод, который используется для передачи сообщений между пользователями, и это должно происходить только тогда, когда получатель вошел в систему.

Однако кажется, что метод is_authenticated() объекта пользователя возвращает True, даже если пользователь вышел из системы (вызывается rest-auth/logout/, что, в свою очередь, должно вызвать выход из системы Django). Что может быть причиной этого? Есть ли что-то, что я пропустил здесь?

Вот код, который у меня есть:

class SendMessage(generics.CreateAPIView):
    permission_classes = (permissions.IsAuthenticated,)
    serializer_class = MessageSerializer

    def perform_create(self, serializer):
        m = self.request.data['msg']
        targetUser = User.objects.get(pk = self.request.data['user'])

        if targetUser.is_authenticated():
            # Send message
        else:
            # Don't send message

person manabreak    schedule 25.06.2015    source источник
comment
2 пользователя? Один отправитель и один получатель? Когда отправитель выполняет какое-либо действие, вы хотите отправить сообщение получателю в зависимости от того, вошел ли получатель в систему или нет? Это сценарий?   -  person Animesh Sharma    schedule 25.06.2015
comment
@AnimeshSharma Да, именно так. Есть два пользователя, и я хочу проверить, аутентифицированы ли они оба (вошли ли они в систему). «Текущий пользователь» проверяется разрешениями, и теперь я пытаюсь проверить другого (целевого пользователя).   -  person manabreak    schedule 25.06.2015


Ответы (3)


К сожалению, метод is_authenticated() всегда возвращает true.

 def is_authenticated(self):
    """
    Always return True. This is a way to tell if the user has been
    authenticated in templates.
    """
    return True

Он предназначен для различения между экземпляром User и экземпляром AnonymousUser, который установлен для User, когда он не проходит аутентификацию.

person Mark Galloway    schedule 25.06.2015
comment
Я наткнулся на тот же фрагмент кода, когда вы опубликовали свой ответ. Однако остается вопрос: как мне проверить, аутентифицирован ли targetUser или нет? - person manabreak; 25.06.2015
comment
Как они не могут быть аутентифицированы? Если текущий пользователь не является анонимным, он аутентифицируется. - person Daniel Roseman; 25.06.2015
comment
@DanielRoseman Участвуют два пользователя: текущий пользователь и целевой пользователь. Я хочу проверить, аутентифицирован ли целевой пользователь (т.е. вошел в систему). - person manabreak; 25.06.2015
comment
@DanielRoseman Я решил принять ваш ответ, поскольку он действительно отвечает на вопрос. Моя ошибка задавать такой второстепенный вопрос, который не очень помог. :) - person manabreak; 25.06.2015
comment
Как пользователь, если я нажму «выйти», я предполагаю, что это завершит мою аутентификацию на сервере, и мне придется снова войти в систему, чтобы что-то сделать. Но если я понимаю, о чем вы говорите, если кто-то завладеет их токеном, он сможет получить доступ к учетной записи, даже если пользователь думает, что сделал ее безопасной? - person Little Brain; 03.02.2019

Попробуйте получить всех аутентифицированных пользователей, а затем проверьте, есть ли среди них целевой пользователь:

from django.contrib.auth.models import User
from django.contrib.sessions.models import Session
from django.utils import timezone

def get_all_logged_in_users_ids():
    # Query all non-expired sessions
    # use timezone.now() instead of datetime.now() in latest versions of Django
    sessions = Session.objects.filter(expire_date__gte=timezone.now())
    uid_list = []

    # Build a list of user ids from that query
    for session in sessions:
        data = session.get_decoded()
        uid_list.append(data.get('_auth_user_id', None))
    return uid_list

class SendMessage(generics.CreateAPIView):
    permission_classes = (permissions.IsAuthenticated,)
    serializer_class = MessageSerializer

    def perform_create(self, serializer):
        m = self.request.data['msg']
        if (self.request.data['user'] in get_all_logged_in_users_ids()):
            # Send message
        else:
            # Don't send message

Справочник.

person Yahya Yahyaoui    schedule 25.06.2015
comment
Потому что я уже знаю, что текущий пользователь аутентифицирован. Я хочу знать, аутентифицирован ли другой пользователь. - person manabreak; 25.06.2015
comment
Ах, хорошо, понял, тогда я удалю свой ответ. - person Yahya Yahyaoui; 25.06.2015
comment
Я изменил ответ. - person Yahya Yahyaoui; 25.06.2015
comment
Ваше решение обращается к базе данных три раза за targetUser, сначала оно извлекает пользователя, затем все сеансы и, наконец, снова фильтрует пользователей. Это кажется действительно неэффективным. - person manabreak; 25.06.2015
comment
Я обновил твой ответ, теперь он попадает в базу только один раз. - person Yahya Yahyaoui; 25.06.2015

Вы неправильно поняли, что проверяет is_authenticated.

Помните, что Интернет — это среда без сохранения состояния. Статус «вошел в систему» ​​на уровне сервера отсутствует: единственная запись о том, вошел ли пользователь в систему или нет, - это наличие файла cookie на компьютере этого пользователя.

Поскольку пользователь всегда может закрыть свой браузер или выключить компьютер без уведомления сервера, нет надежного способа узнать, действительно ли пользователь вошел в систему. Единственный способ приблизиться к этому — это иметь какой-то повторный вызов Ajax каждые несколько секунд, отправляя сообщение в представление, которое обновляет запись пользователя с текущим временем. Затем вы можете проверить, действительно ли пользователь обновлялся в течение последних нескольких секунд. Однако это не будет абсолютно надежным.

В качестве альтернативы вы можете использовать какую-то систему длительного опроса, чтобы держать канал открытым.

person Daniel Roseman    schedule 25.06.2015
comment
Называется ли это аутентификацией или чем-то еще, мне просто нужно знать, щелкнул ли пользователь выход в своем мобильном приложении или нет. - person manabreak; 25.06.2015
comment
И что происходит, когда они нажимают «Выйти»? Вас не волнует, если они просто закроют приложение и больше никогда им не воспользуются — вы будете считать это просто входом в систему? - person Daniel Roseman; 25.06.2015
comment
Токен авторизации удаляется. Мне просто интересно, есть ли способ проверить это без дополнительного запроса для каждого сообщения. - person manabreak; 25.06.2015