【问题标题】:Django: custom http header authentificationDjango:自定义 http 标头身份验证
【发布时间】:2019-04-09 01:29:45
【问题描述】:

我想为我的 Django 1.11 项目创建一个身份验证。如果请求包含标头:X_USERNAME,则将对用户进行身份验证。 我正在使用通用视图,所以我使用LoginRequiredMixin 来控制访问。

我制作了这个自定义身份验证类:

class CustomAuthentication:
    def authenticate(self, request):
        username = request.META.get('X_USERNAME')
        logging.warning(username)
        if not username:
            return None
        try:
            user = User.objects.get(username=username)
        except User.DoesNotExist:
            user = User(username=username)
            user.is_staff = False
            user.is_superuser = False
            if request.META.get('X_GROUPNAME') == 'administrator':
                user.is_staff = True
                user.is_superuser = True
            user.save()
        return user, None

    def get_user(self, user_id):
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None

我在我的设置中添加了它:

AUTHENTICATION_BACKENDS = ['path.to.file.CustomAuthentication']

但我不能让它工作。我被重定向到不存在的/accounts/login/?next=

提前致谢!

编辑:

我还尝试创建一个子类,如下所述:Django RemoteUser documentation,因为它看起来像我想要实现的目标:

class CustomAuthentication(RemoteUserMiddleware):
    header = 'HTTP_X_USERNAME'

它给了我同样的结果。

【问题讨论】:

  • 您是否尝试在authenticate() 方法中放置额外的日志语句以查看正在执行的代码路径?
  • 是的,我做到了,似乎从未调用过此函数。也许应该在登录页面中手动调用authenticate() 方法?这不是我想要的,因为我不想使用登录页面。

标签: python django authentication http-headers


【解决方案1】:

似乎authenticate() 方法除了request 参数之外还必须指定usernamepassword 参数。没有这些,Django 会忽略后端(参见 Django 2.0 中的django.contrib.auth.__init__._authenticate_with_backend)。

在您的情况下,您应该能够将这些参数默认为 None,因为您通过标头提供用户名。

class CustomAuthentication:
    def authenticate(self, request, username=None, password=None):
        username = request.META.get('X_USERNAME')
        ...

或者,使用**credentials:

def authenticate(self, request, **credentials):

【讨论】:

  • 我试过了,但是authenticate()方法仍然没有执行。我想我没有使用正确的身份验证。不过,这是一条有用的信息。
  • 奇怪。当我从我的测试后端遗漏usernamepassword 属性时,authenticate() 方法不会被调用,否则 Django 会调用它。
【解决方案2】:

我终于找到了解决办法:

在 authentication.py 中:

from django.contrib.auth.middleware import RemoteUserMiddleware

class CustomMiddleware(RemoteUserMiddleware):
    header = 'HTTP_X_USERNAME'

第二次导入是强制性的,我不知道为什么。

在settings.py中:

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'app.authentication.CustomMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

AUTHENTICATION_BACKENDS = ['app.authentication.RemoteUserBackend']

最后在基于类的视图中我使用LoginRequiredMixin

见:https://docs.djangoproject.com/en/3.2/howto/auth-remote-user/#configuration

【讨论】:

  • 似乎不再工作:属性错误:...对象没有属性'authenticate'
猜你喜欢
  • 2016-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-07
  • 1970-01-01
  • 2015-11-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多