首页 > 解决方案 > 具有登录链接的登录用户

问题描述

我想向用户发送登录链接。

我知道有一些 OneTimePassword 应用程序具有数千种功能。但我只想要一些简单而简单的方式通过登录链接登录用户。

我的问题是这是否是解决此问题的正确方法。就像最佳实践和 DRY 代码一样。

所以我设置了一个存储三行的表。1. 'user' 用户 2. 'autogeneratedkey' 自动生成的密钥 3. 'created_at' 时间戳

当他们登录时,将向他们发送一封邮件,其中包含有效期为 nn 分钟的登录链接。所以登录会是这样的

https://example.net/login/?username=USERNAME&autogeneratedkey=KEY

对我来说,棘手的部分是找出一个检查这个并登录用户的好方法。我只是在这里猜测。但这会是一个好方法吗?

class login(generic.CreateView):
  def get(self, request, *args, **kwargs):
    try:
        autgeneratedkey = self.request.GET.get('autgeneratedkey', '')
        username = self.request.GET.get('username', '')

        obj_key = Login.objects.filter(autgeneratedkey=autgeneratedkey)[0]
        obj_user = Login.objects.filter(userusername=username)[0]

        try:
            if obj_user == obj_key: #Compare the objects if same
                if datetime.datetime.now() < (obj_key.created_at + datetime.timedelta(minutes=10)): #Check so the key is not older than 10min
                    u = CustomUser.objects.get(pk=obj_user.user_id)
                    login(request, u)
                    Login.objects.filter(autgeneratedkey=autgeneratedkey).delete()
                else:
                    return login_fail
            else:
                return login_fail

    except:
        return login_fail

    return redirect('index')

def login_fail(self, request, *args, **kwargs):
    return render(request, 'login/invalid_login.html')

首先使用自动生成的密钥然后使用用户名调用同一个帖子感觉很草率。也堆叠 if-else 感觉俗气。

标签: djangopython-3.xdjango-views

解决方案


我不会在获取请求中发送用户名。只需发送一个自动生成的密钥。

http://example.com/login?key=random-long-string

然后这个数据库模式(这是一个新表,因为我不知道是否Login已经被使用。

LoginKey ( id [PK], user [FK(CustomUser)], key [Unique], expiry )

当用户提供电子邮件时,您会创建一个新的LoginKey.

然后做这样的事情:

def get(self, request, *args, **kwargs):
  key = request.GET.get('key', '')
  if not key:
    return login_fail

  login_key = LoginKey.objects.get(key=key)
  if login_key is None or datetime.datetime.now() > login_key.expiry:
    return login_fail

  u = login_key.user
  login(request, u)
  login_key.delete()
  return redirect('index')

推荐阅读