手动login没有密码的用户

我希望你能帮助我find最好的方法来实现手动(服务器端启动)login, 而不使用密码。 让我解释一下工作stream程:

  • 用户注册
  • 谢谢! 带有激活链接的电子邮件已发送给blablabla
  • (帐户现在存在但标记为未启用)
  • 用户打开电子邮件,点击链接
  • (帐号已启用)
  • 谢谢! 您现在可以使用该网站

我想要做的就是在用户点击电子邮件链接后login,以便他可以立即开始使用网站。

我不能使用他的密码,因为它是在数据库中encryption,是唯一的select写一个自定义身份validation后端?

您不需要密码就可以login用户auth.login函数只需要一个User对象,当您启用该帐户时,您大概已经从数据库中获取了该对象。 所以你可以直接通过login

当然,您需要非常小心,用户无法欺骗到现有已启用帐户的链接,然后该帐户会自动以该用户的身份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) 

…等

编辑

嗯,没有注意到要求使用authenticate因为它增加了额外的属性。 看代码,它所做的只是一个与authentication后端的模块path相当的backend属性。 所以你可以假冒它 – 在上面的login电话之前,做这个:

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

丹尼尔的回答非常好。

另一种方法是在自定义授权后端创build一个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的所有版本中,为了让用户login,他们必须通过应用程序的后端进行身份validation (由AUTHENTICATION_BACKENDS设置控制)。

如果您只是想强制login,则可以声称用户已经从该列表中的第一个后端进行身份validation:

 from django.conf import settings from django.contrib.auth import login # Django 1.10+ login(request, user, backend=settings.settings.AUTHENTICATION_BACKENDS[0]) # Django <1.10 - fake the authenticate() call user.backend = settings.AUTHENTICATION_BACKENDS[0] login(request, user) 

你可以使用ska包,它具有无密码login到Django实现。 ska与authentication令牌一起工作,其安全性基于SHARED_KEY,对于涉及的所有方(服务器)应该是相等的。

在客户端(请求无密码login的一方),您使用ska生成一个URL并对其进行签名。 例:

 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秒。 您可以通过certificatelifetime参数来自定义。

在服务器端(用户login的站点),考虑到你已经正确安装了ska ,当用户访问URL(用户名匹配)或其他方式创buildURL时,用户就会login。 您可以在项目的Django设置中自定义3个callback。

USER_GET_CALLBACK(string):如果用户从数据库(现有用户)成功获取,则触发。 USER_CREATE_CALLBACK(string):在创build用户(用户不存在)后立即触发。 USER_INFO_CALLBACK(string):成功validation时触发。

有关更多信息,请参阅文档( http://pythonhosted.org/ska/ )。

回答的回答。

一种编写后端的方法:

 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', ] 

因为帐户激活不如login本身。 根据https://docs.djangoproject.com/en/1.9/topics/auth/customizing/#specifying-authentication-backends

AUTHENTICATION_BACKENDS的顺序很重要,所以如果在多个后端使用相同的用户名和密码,Django将在第一次正面匹配时停止处理。

请注意,即使密码不正确,此代码也会validation您的用户。

Interesting Posts