首页 文章

Django,request.user始终是匿名用户

提问于
浏览
7

我正在使用Django的自定义身份验证后端(运行couchdb) . 我有一个自定义用户模型 .

作为登录的一部分,我正在执行 request.user = user 并在会话中保存用户ID . 但是,在后续请求中,我无法检索request.user . 它始终是AnonymousUser . 但是,我可以从会话中检索用户ID,并确认正确设置了会话cookie .

我错过了什么?

我不想使用关系数据库,因为我想在couchdb中维护我的所有用户数据 .

Edit :我写了一个不从Django的auth用户继承的类 . 但它具有用户名和电子邮件属性 . 出于这个原因,我的后端不会返回一个派生自auth User的类 .

6 回答

  • 4

    请详细说明 . 如果您使用的是自定义用户模型(与自定义用户PROFILE模型不同),那么您基本上是独立的,并且django.contrib.auth框架无法帮助您进行身份验证 . 如果您正在编写自己的身份验证系统但未使用django.contrib.auth,那么您需要将其关闭,因为它似乎干扰了您的系统 .

  • 0

    request.userdjango.contrib.auth.middleware.AuthenticationMiddleware 设置 .

    检查 django/contrib/auth/middleware.py

    class LazyUser(object):
        def __get__(self, request, obj_type=None):
            if not hasattr(request, '_cached_user'):
                from django.contrib.auth import get_user
                request._cached_user = get_user(request)
            return request._cached_user
    
    class AuthenticationMiddleware(object):
        def process_request(self, request):
            request.__class__.user = LazyUser()
            return None
    

    然后查看 django/contrib/auth/__init__.py 中的 get_user 函数:

    def get_user(request):
        from django.contrib.auth.models import AnonymousUser
        try:
            user_id = request.session[SESSION_KEY]
            backend_path = request.session[BACKEND_SESSION_KEY]
            backend = load_backend(backend_path)
            user = backend.get_user(user_id) or AnonymousUser()
        except KeyError:
            user = AnonymousUser()
        return user
    

    您的后端需要实现 get_user 功能 .

  • 1

    你说你've written a custom authentication backend, but in fact what you seem to have written is a complete custom authentication app, which doesn'与Django的接口 contrib.auth .

    如果要将非关系数据库用于身份验证数据,则需要创建一个提供两种方法的类: get_user(user_id)authenticate(**credentials) . 见the documentation . 一旦您对用户进行了身份验证,您只需调用Django的常规登录方法即可 . 应该没有理由手动设置 request.user 或将任何内容放入会话中 .

    Update after edit 这与它无关 . 不要求用户类派生自 auth.models.User . 您仍然只需要定义一个将返回用户类实例的 get_user 方法 .

  • 4

    我也有自定义身份验证后端,并且在 successful 身份验证和登录后总是得到 AnonymousUser . 我的后端有 get_user 方法 . 我缺少的是 get_user 必须仅通过 pk 获取用户,而不是通过电子邮件或 authenticate 中的任何凭据:

    class AccountAuthBackend(object):
    
    @staticmethod
    def authenticate(email=None, password=None):
        try:
            user = User.objects.get(email=email)
            if user.check_password(password):
                return user
        except User.DoesNotExist:
            return None
    
    @staticmethod
    def get_user(id_):
        try:
            return User.objects.get(pk=id_) # <-- tried to get by email here
        except User.DoesNotExist:
            return None
    

    在文档中很容易错过这一行:

    get_user方法接受user_id - 可以是用户名,数据库ID或其他任何内容,但必须是User对象的主键 - 并返回User对象 .

    碰巧 email 不是我架构中的主键 . 希望这能节省一些时间 .

  • 10

    当我使用自定义身份验证后端时,我遇到了类似的问题 . 我在方法 get_user 中使用了与主键不同的字段 . 它在使用主键后直接解决,主键必须是数字(不是str)

    def get_user(self, user_id):
        try:
            return User.objects.get(pk=user_id) # <-- must be primary key and number
        except User.DoesNotExist:
            return None
    
  • 0

    在使用Authorization标头发送令牌后,令牌将在调度函数中获得,如下所示:'''

    def dispatch(self, request, *args, **kwargs):
    
        self.args = args
        self.kwargs = kwargs
        request = self.initialize_request(request, *args, **kwargs)
        self.request = request
        self.headers = self.default_response_headers  # deprecate?
    
        try:
            self.initial(request, *args, **kwargs)
    
            # Get the appropriate handler method
            if request.method.lower() in self.http_method_names:
                handler = getattr(self, request.method.lower(),
                                  self.http_method_not_allowed)
            else:
                handler = self.http_method_not_allowed
    
            response = handler(request, *args, **kwargs)
    
        except Exception as exc:
            response = self.handle_exception(exc)
    
        self.response = self.finalize_response(request, response, *args, **kwargs)
        return self.response
    

    所以你使用的是django_role_permission的HasRoleMixin,这个mixin的调度方法将隐藏视图的调度 . 我认为解决方案是重新定义角色权限的混合

相关问题