没有密码的django身份验证

Posted

技术标签:

【中文标题】没有密码的django身份验证【英文标题】:django authentication without a password 【发布时间】:2011-09-27 11:02:16 【问题描述】:

我在 django 中使用默认身份验证系统,但我添加了一个 OpenID 库,我可以在其中通过 OpenID 对用户进行身份验证。我想做的是让他们登录,但似乎使用默认的 django 身份验证系统,我需要他们的密码来验证用户身份。有没有办法在不实际使用他们的密码的情况下解决这个问题?

我想做这样的事情......

user = ... # queried the user based on the OpenID response
user = authenticate(user) # function actually requires a username and password
login(user)

我宁愿放弃authenticate 函数,但它附加了一个backend 字段,这是登录所必需的。

【问题讨论】:

Manually logging in a user without password 可能重复。 【参考方案1】:

为此编写自定义身份验证后端很简单。如果您使用以下内容创建 yourapp/auth_backend.py:

from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.models import User


class PasswordlessAuthBackend(ModelBackend):
    """Log in to Django without providing a password.

    """
    def authenticate(self, username=None):
        try:
            return User.objects.get(username=username)
        except User.DoesNotExist:
            return None

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

然后添加到你的settings.py:

AUTHENTICATION_BACKENDS = (
    # ... your other backends
    'yourapp.auth_backend.PasswordlessAuthBackend',
)

在您看来,您现在可以在没有密码的情况下调用 authenticate:

user = authenticate(username=user.username)
login(request, user)

【讨论】:

这很好用,但要注意 - 如果您想在某些情况下使用常规身份验证,以及在其他情况下使用无密码身份验证,请确保防止您的新后端导致每次尝试使用有效用户名成功 - 请记住,在调用 authenticate() 时会尝试所有后端。在我的情况下,我需要包含一个特殊的令牌参数,以确保 authenticate() 的调用者确实希望无密码身份验证工作。 @Richard 您如何实现常规身份验证和无密码身份验证。我正在尝试实现它,但它正在调用常规身份验证方法。 以上代码不适用于 Django 2.1。它没有调用 PasswordlessAuthBackend 类的身份验证方法。但它适用于 Django 2.0 @SanketPatel 我怀疑在较新的 Django 版本中,def authenticate 必须采用request 参数,如another answer for this question。 @SanketPatel 更多信息在***.com/a/54370236/263061。【参考方案2】:

这有点小技巧,但如果您不想重写一堆东西,请删除身份验证

user.backend = 'django.contrib.auth.backends.ModelBackend'
login(request, user)

user 将是您的 User 对象

【讨论】:

这是一种可能的解决方案,但它不会存储在会话中,因此如果您打开一个新标签并转到该站点,则必须重新登录。 这将保存在会话中,并在后续视图中工作。唯一的问题是您设置的后端必须包含在 AUTHENTICATION_BACKENDS 设置中。我希望我可以撤消我的反对票,但我不能。 @voodoogiant,我遇到了完全相同的问题,即会话未存储。但奇怪的是,前 2 个 XHR 请求可以正确地从 session-id 获取会话数据。但是后来的 XHR 请求没有,并且 Django 服务器将 cookie 中的 session-id 设置为空白字符串作为响应。你知道为什么吗?以及如何解决?【参考方案3】:

为了在没有密码的情况下进行身份验证,请在您的settings.py

AUTHENTICATION_BACKENDS = [
# auth_backend.py implementing Class YourAuth inside yourapp folder
    'yourapp.auth_backend.YourAuth', 
# Default authentication of Django
    'django.contrib.auth.backends.ModelBackend',
]

在你的auth_backend.py:

注意:如果您的应用有自定义模型,请从 .models CustomUser 导入

from .models import User 
from django.conf import settings

# requires to define two functions authenticate and get_user

class YourAuth:  

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

在您的自定义登录请求视图中:

# Your Logic to login user
userName = authenticate(request, username=uid)
login(request, userName)

如需进一步参考,请使用django documentation here。

【讨论】:

感谢格式化以提高可读性@OliviaStork 我可以只在我项目的一个应用上使用它,而不是应用到项目的其余部分吗? 'uid' 未定义。 'uid' 指的是什么? 'uid' 是在逻辑中存储用户 ID 的自定义参数 @Timothyjames67 是的,您可以制作自定义用户模型【参考方案4】:

您可以通过创建自己的authentication backend 并将其添加到AUTHENTICATION_BACKENDS 设置来轻松解决此问题。

已经有一些 OpenID 后端可用,因此通过一些搜索,您可以省去编写后端的麻烦。

【讨论】:

我遇到了 django OpenID 后端的问题,因为它们与 Google 独特的 OpenID 方式不兼容。无论如何,就像我说的,我已经有一个基于密码的后端,我只想在某些情况下使用 OpenID——而不是切换到严格的 OpenID 后端。 @voodoogiant:根据关键字参数选择身份验证后端。因此,如果您将openid_token 用于您的 OpenID 后端,将usernamepassword 用于您的普通身份验证系统,那么它们都将起作用。

以上是关于没有密码的django身份验证的主要内容,如果未能解决你的问题,请参考以下文章

django rest framework jwt 使用电子邮件和密码进行身份验证

Django REST to React - 无需密码即可获取社交身份验证令牌

无法使用用户名/密码登录令牌端点:drf 令牌身份验证和自定义用户模型,Django

使用多个数据库进行 Django 身份验证

在Django中定制身份验证

Django 2.1.2 密码重置身份验证视图:找不到“password_reset_confirm”的反向