【问题标题】:is_authenticated returns True for logged out useris_authenticated 为已注销的用户返回 True
【发布时间】:2015-09-11 23:18:42
【问题描述】:

我正在使用 Django、Django REST 框架、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

【问题讨论】:

  • 有 2 个用户吗?一个发送者和一个接收者?当发送者执行某些操作时,您希望根据接收者是否登录向接收者发送消息?是这样的场景吗?
  • @AnimeshSharma 是的,完全正确。有两个用户,我想检查他们是否都经过身份验证(登录)。 '当前用户'由权限检查,现在我正在尝试检查另一个(目标用户)。

标签: django authentication django-rest-framework django-allauth django-rest-auth


【解决方案1】:

尝试获取所有经过身份验证的用户,然后检查目标用户是否在其中:

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

Reference.

【讨论】:

  • 因为我已经知道当前用户是经过身份验证的。我想知道其他用户是否也通过了身份验证。
  • 啊好的,知道了,那我就删掉我的答案。
  • 我改了答案。
  • 您的解决方案每个targetUser 访问数据库三次,它首先获取用户,然后是所有会话,最后再次过滤用户。好像真的没效果。
  • 我更新了你的答案,现在它只访问数据库一次。
【解决方案2】:

您误解了is_authenticated 正在检查的内容。

请记住,网络是一个无状态的环境。没有服务器级别的“登录”状态:用户是否登录的唯一记录是该 cookie 是否存在于该用户的机器上。

由于用户总是有可能在不通知服务器的情况下关闭浏览器或关闭机器,因此没有可靠的方法可以知道用户是否真正登录。您可以接近的唯一方法也就是说,每隔几秒就会有某种重复的 Ajax 调用,发布到一个用当前时间更新用户记录的视图。然后您可以检查用户是否确实在最后几秒钟内进行了更新。不过,这并不完全可靠。

或者,您可以考虑使用某种长轮询系统来保持通道打开。

【讨论】:

  • 无论是身份验证还是其他什么,我只需要知道用户是否在他们的移动应用上点击了“注销”。
  • 当他们点击注销时会发生什么?你不在乎他们是否只是关闭应用程序并且不再使用它 - 你会算作登录吗?
  • 授权令牌被删除。我只是想知道是否有一种方法可以在不对每条消息进行额外查询的情况下进行检查。
【解决方案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 实例,这是用户未通过身份验证时设置的内容。

【讨论】:

  • 我在您发布答案时偶然发现了同一段代码。但是,问题仍然存在:如何检查targetUser 是否经过身份验证?
  • 他们怎么不能被认证?如果当前用户不是匿名的,则他们经过身份验证。
  • @DanielRoseman 涉及两个用户,当前用户和目标用户。我想检查目标用户是否经过身份验证(即登录)。
  • @DanielRoseman 我选择接受您的回答,因为它是真正回答问题的人。问这样一个偏题的问题是我的错误,它没有多大帮助。 :)
  • 作为用户,如果我单击“注销”,我认为这将结束我在服务器上的身份验证,我必须再次登录才能执行任何操作。但是,如果我理解您的意思,如果有人拿到了他们的令牌,即使用户认为他们已经确保其安全,他们也可以访问该帐户?
猜你喜欢
  • 2016-04-21
  • 2022-07-19
  • 1970-01-01
  • 2019-12-05
  • 2011-06-26
  • 1970-01-01
  • 2011-05-24
  • 2018-07-08
  • 2018-06-13
相关资源
最近更新 更多