没有密码的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 后端,将username
和password
用于您的普通身份验证系统,那么它们都将起作用。以上是关于没有密码的django身份验证的主要内容,如果未能解决你的问题,请参考以下文章
django rest framework jwt 使用电子邮件和密码进行身份验证
Django REST to React - 无需密码即可获取社交身份验证令牌