希望您能帮助我找出实现手册(服务器端启动)登录的最佳方法 没有 使用密码。让我解释一下工作流程:

  • 用户寄存器
  • 谢谢!带有激活链接的电子邮件已发送
  • (现在存在帐户,但未启用未启用)
  • 用户打开电子邮件,单击链接
  • (启用帐户)
  • 谢谢!您现在可以使用该网站

我要做的是在用户单击电子邮件链接后登录用户,以便他可以立即开始使用该网站。

我无法使用他的密码,因为它已在DB中加密,是唯一的选项编写自定义身份验证后端?

有帮助吗?

解决方案

您不需要密码来记录用户。 auth.login 功能 只需一个 User 对象,当您启用帐户时,您可能已经从数据库中获取了对象。这样你就可以直接传递给 login.

当然,你需要 非常 小心用户无法欺骗链接到现有的已经启用的帐户,然后将其作为用户自动登录。

from django.contrib.auth import login

def activate_account(request, hash):
    account = get_account_from_hash(hash)
    if not account.is_active:
        account.activate()
        account.save()
        user = account.user
        login(request, user)

... ETC。

编辑:

嗯,没有注意到使用的要求 authenticate 因为它添加了额外的属性。查看代码,它所做的只是 backend 属性等效于身份验证后端的模块路径。因此,您可以伪造它 - 在上面的登录电话之前,请执行此操作:

user.backend = 'django.contrib.auth.backends.ModelBackend'

其他提示

丹尼尔的答案非常好。

另一种方法是在自定义授权后端创建HashModelbackend https://docs.djangoproject.com/en/1.8/topics/auth/customizing/#writing-an-authentication-backend 像这样:

class HashModelBackend(object):
    def authenticate(self, hash=None):
        user = get_user_from_hash(hash)
        return user

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

然后将其安装在您的设置中:

AUTHENTICATION_BACKENDS = (
    'myproject.backends.HashModelBackend',
    'django.contrib.auth.backends.ModelBackend',
)

那么您的观点就是这样:

def activate_account(request, hash):
    user = authenticate(hash=hash)
    if user:
        # check if user is_active, and any other checks
        login(request, user)
    else:
        return user_not_found_bad_hash_message

从Django 1.10开始,该过程已简化。

在所有版本的Django中,为了登录用户,他们必须是 由您的应用程序的后端之一验证 (由 AUTHENTICATION_BACKENDS 环境)。

如果您只想强制登录名,则可以声称该列表的第一个后端对用户进行身份验证:

from django.conf import settings
from django.contrib.auth import login


# Django 1.10+
login(request, user, backend=settings.AUTHENTICATION_BACKENDS[0])

# Django <1.10 -  fake the authenticate() call
user.backend = settings.AUTHENTICATION_BACKENDS[0]
login(request, user)

响应 的答案。

一种写您的后端的方法:

from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend

class HashModelBackend(ModelBackend):

def authenticate(self, username=None, **kwargs):
    UserModel = get_user_model()
    if username is None:
        username = kwargs.get(UserModel.USERNAME_FIELD)
    try:
        user = UserModel._default_manager.get_by_natural_key(username)
        return user
    except UserModel.DoesNotExist:
        return None

答案是基于 django.contrib.auth.backends.modelbackend 源代码。这是Django 1.9的实际

我宁愿将自定义后端放置在Django的默认设置下方:

AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.ModelBackend',
    'yours.HashModelBackend',
]

因为帐户激活比登录本身的可能性少。根据 https://docs.djangoproject.com/en/1.9/topics/auth/customizing/#specifying-authentication-backends:

Authentication_backend的顺序很重要,因此,如果相同的用户名和密码在多个后端有效,Django将在第一个正面匹配下停止处理。

当心即使使用不正确的密码,此代码也会验证您的用户。

您可以使用 ska 软件包,已实现了无密码登录到Django。 ska 使用身份验证令牌及其安全性的工作基于共享_KEY,该keyke应该对所有各方(服务器)相同。

在客户端(请求无密码登录的政党),您可以生成URL并使用 ska. 。例子:

from ska import sign_url
from ska.contrib.django.ska.settings import SECRET_KEY

server_ska_login_url = 'https://server-url.com/ska/login/'

signed_url = sign_url(
    auth_user='test_ska_user_0',
    secret_key=SECRET_KEY,
    url=server_ska_login_url
    extra={
        'email': 'john.doe@mail.example.com',
        'first_name': 'John',
        'last_name': 'Doe',
    }
)

令牌的默认寿命为600秒。您可以通过证明 lifetime 争论。

在服务器端(用户登录到的站点),请记住您已经安装了 ska 正确地,如果使用URL(用户名匹配)或其他创建的URL,则可以在访问URL时登录。您可以在项目的Django设置中自定义3个回调。

  • USER_GET_CALLBACK (字符串):如果用户从数据库(现有用户)成功获取,则解雇。
  • USER_CREATE_CALLBACK (字符串):在创建用户后立即发射(不存在用户)。
  • USER_INFO_CALLBACK (字符串):成功身份验证后被解雇。

请参阅文档(http://pythonhosted.org/ska/)更多。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top