我正在尝试实现一种身份验证方法,其中:
请注意,这不适用于任何关键任务生产软件-我正在阅读《服从测试山羊O'Reilly》一书,这是作者为我们实施的身份验证方法。
因此,当用户单击电子邮件中的链接时,这是处理该链接的视图功能:
from django.contrib.auth import authenticate, login
def login(request):
uid = request.GET.get('uid')
user = authenticate(uid=uid)
if user is not None:
login(request, user)
return redirect('/')
在该视图函数中,我们调用由authenticate
提供的django.contrib.auth
函数。这是该功能:
def authenticate(request=None, **credentials):
"""
If the given credentials are valid, return a User object.
"""
for backend, backend_path in _get_backends(return_tuples=True):
backend_signature = inspect.signature(backend.authenticate)
try:
backend_signature.bind(request, **credentials)
except TypeError:
# This backend doesn't accept these credentials as arguments. Try the next one.
### I have confirmed that the bind function above, and specifically the _bind private function,
### is throwing the TypeError so my custom auth function is never getting called
continue
try:
user = backend.authenticate(request, **credentials)
except PermissionDenied:
# This backend says to stop in our tracks - this user should not be allowed in at all.
break
if user is None:
continue
# Annotate the user object with the path of the backend.
user.backend = backend_path
return user
请注意,这是Django框架代码-我没有编写此代码。由于某些原因,行backend_signature.bind(request, **credentials)
抛出了TypeError
,因此未调用我的自定义auth函数。 (我已经通过打印语句确认了这一点)
这里是AUTHENTICATION_BACKENDS
中的settings.py
。 _get_backends
语句中的for
函数将查找此设置,以确定应使用哪种身份验证后端。我可以确认它找到了我的自定义后端-由于某种原因,传入的参数无法绑定到它:
AUTHENTICATION_BACKENDS = [
'accounts.authentication.PasswordlessAuthenticationBackend',
]
这是实际的自定义后端代码:
def authenticate(self, uid):
if not Token.objects.filter(uid=uid).exists():
return None
token = Token.objects.get(uid=uid)
try:
user = ListUser.objects.get(email=token.email)
return user
except ListUser.DoesNotExist:
return ListUser.objects.create(email=token.email)
在此先感谢您的帮助-如果您可以提供更多信息,请告诉我。
答案 0 :(得分:0)
想通了。
我的身份验证功能需要带一个请求参数,因为默认情况下为None
的请求参数是从Django authenticate
函数中层叠下来的。
所以我的自定义身份验证功能签名看起来像这样:
authenticate(self, request, uid)