【问题标题】:Is it possible to make email confirmation key shorter with dj-rest-auth?是否可以使用 dj-rest-auth 缩短电子邮件确认密钥?
【发布时间】:2021-05-08 12:51:37
【问题描述】:

我正在为移动应用程序制作一个休息 api。我正在使用dj-rest-auth 包进行整个身份验证过程。整体身份验证功能运行良好,但我要修改的一件事是使电子邮件确认密钥更短。

用户会收到这样的电子邮件。

Please use this key to confirm your email.

MjE:1l7ZhR:f6U2RWlx2kEJY2jXzFuAuKpKclNyc3MpaKmeiEFGp3Y

在我的电子邮件中验证 api 用户需要输入整个密钥进行验证。

有什么办法可以缩短这个密钥,以便从用户的角度来看它会更好(我认为)?

我在这里制作了我的自定义适配器。

class MyAdapter(DefaultAccountAdapter):
    def send_confirmation_mail(self, request, emailconfirmation, signup):
        current_site = get_current_site(request)
        activate_url = self.get_email_confirmation_url(
            request,
            emailconfirmation)
        ctx = {
            "user": emailconfirmation.email_address.user,
            "activate_url": activate_url,
            "current_site": current_site,
            "key": emailconfirmation.key,

        }

【问题讨论】:

    标签: django django-rest-framework django-rest-auth


    【解决方案1】:

    查看您的代码,我猜您正在使用django-allauth (https://github.com/pennersr/django-allauth)。

    在此示例中,我假设用户已通过身份验证,并且验证码不必是唯一的。

    如果您想创建一个较短的密钥并将其存储在 db 中,您应该创建自定义模型,其中 key 适合您的需求(本示例中为 4 位 - 我假设您的用户手动输入) :

    class ActivationKey(models.Model):
        user = models.ForeignKey(User, verbose_name=_("user"), on_delete=models.CASCADE)
        key = models.PositiveSmallIntegerField(_("key"))
        created_at = models.DateTimeField(auto_now_add=True)
        
        @classmethod
        def create(cls, user):
            key = random.randint(1000, 9999)
            return cls._default_manager.create(user=user, key=key)
    

    我们可以在用户创建后生成密钥(覆盖 save() 或在发送电子邮件之前使用信号或创建)。正如你所指出的,你可以覆盖send_confirmation_mail,所以为了简单起见,我在这个例子中使用它:

    class MyAdapter(DefaultAccountAdapter):
        def send_confirmation_mail(self, request, emailconfirmation, signup):
            current_site = get_current_site(request)
            ctx = {
                "user": emailconfirmation.email_address.user,
                "activate_url": reverse("account_confirm_key"),  # depends on you - if you need it at all
                "current_site": current_site,
                "key": ActivationKey.objects.create(user=user) # create key
            }
            if signup:
                email_template = "account/email/email_confirmation_signup"
            else:
                email_template = "account/email/email_confirmation"
            self.send_mail(email_template, emailconfirmation.email_address.email, ctx)
    

    接下来您应该为确认代码创建自定义端点并激活用户:

     class VerifyUserView(APIView):
        permission_classes = [permissions.IsAuthenticated]
    
        def post(self, request):  # or change to get if more proper to you
            key = request.data.get("key")
            if not key:
                return Response({"error": _("Key is missing")}, status=status.HTTP_400_BAD_REQUEST)
            if not ActivationCode.objects.filter(user=request.user, key=key).exists():
               return Response({"error": _("Wrong activation key")}, status=status.HTTP_400_BAD_REQUEST)
    
            get_adapter(request).confirm_email(request, user.email)  # confirm method from adapter
            return Response({"status": "ok"})
    

    记住设置: ACCOUNT_ADAPTER = MyAdapter

    关于 django-allauth:

    电子邮件验证的默认配置 (https://dj-rest-auth.readthedocs.io/en/latest/configuration.html) 是 ACCOUNT_EMAIL_CONFIRMATION_HMAC = True,这意味着 django 将生成 HMAC (https://en.wikipedia.org/wiki/HMAC) 密钥。 如果您将选项更改为 False 密钥将生成并存储在 EmailConfirmation 模型中:https://github.com/pennersr/django-allauth/blob/da5ccdcf171e32ab1a438add3af38957f5a0659a/allauth/account/models.py#L100 但对您来说可能太长 - 64 个字符

    另一种选择是您为用户创建短链接(例如 bit.ly)而不更改任何内容。或者,如果这是针对移动应用程序,您可以创建深度链接,因此在单击确认链接(甚至很长)后,用户将被重定向到移动应用程序,然后移动应用程序向后端发送请求?

    【讨论】:

    猜你喜欢
    • 2020-12-22
    • 2017-02-01
    • 2020-01-09
    • 1970-01-01
    • 2019-04-17
    • 1970-01-01
    • 2021-07-22
    • 2019-12-31
    • 2012-12-26
    相关资源
    最近更新 更多