【问题标题】:Encrypt and decrypt in Django在 Django 中加密和解密
【发布时间】:2021-12-16 16:57:37
【问题描述】:

我正在努力在我的电子邮件中实施“取消订阅链接”。我正在为未订阅用户维护一个表。

一旦用户点击退订链接,我想知道电子​​邮件地址。当然,我不能将它作为 get 参数发送,因为很容易修改它。

例如。情况是 - 我想向我的 10 个朋友发送电子邮件,每封电子邮件都是 HTML 电子邮件并且有一个取消订阅 URL,所以如果用户点击链接,那么他会被添加到我的 UnsubscribedUser 模型中,然后我没有不要给他们发邮件。

我想以某种方式加密电子邮件地址,将其作为 get 参数传递,然后在视图中解密并将其存储在我的数据库中。 我不知道我应该如何在 Django 中执行此操作。 如果有更好的方法来实现这一点,请告诉我。

【问题讨论】:

  • 为什么要加密呢?而不仅仅是散列?
  • 那么我应该如何在 Django 中进行散列和反散列?
  • 嗯,散列函数的想法是不可能在合理的时间内取消散列。密码通常也使用哈希函数存储......
  • 此外,我真的不知道“未订阅用户”表是否符合 GDPR。如果我没记错的话,如果不再需要,欧盟用户的数据应该被销毁。

标签: django encryption unsubscribe


【解决方案1】:

通常加密也不是一个好主意,因为如果知道解密密钥,人们就可以解密所有可能的内容,而且还可以很容易地开始使用加密密钥来破解这个应用程序:如果我以某种方式发现加密密钥,我可以构造一个 URL,例如重置任意电子邮件地址的密码,从而重置 Bob 的密码,然后以 Bob 身份登录。

一个典型的解决方案是构建一个“取消订阅会话”表。如果有人要求取消订阅,您可以将该人添加到表中,然后添加某种 随机 id 到其中。最好不要使用主键之类的东西,因为可以预测上一个和下一个ids 将是什么,然后人们可以“破解”这个系统来确认另一个系统的退订人。

我们因此创建了一个表,例如一个 GUID(全局唯一标识符):

from datetime import datetime, timedelta
from django.conf import settings
from django.db.models import CASCADE, DateTimeField, ForeignKey, Model, UUIDField
from uuid import uuid4

def tomorrow():
    return datetime.now() + timedelta(days=1)

class UnsubscribingUser(Model):
    uuid = UUIDField(default=uuid4, editable=False, unique=True)
    user = ForeignKey(settings.AUTH_USER_MODEL, on_delete=CASCADE)
    expires = DateTimeField(default=tomorrow)

所以现在如果你想退订某人,你可以构造这样的UnsubscribingUser模型实例,并发送一封带有链接的电子邮件:

def unsubscribe(request):
    uu = UnsubscribingUser.objects.create(user=request.user)

    # send mail with uu.uuid
    # ...
    pass

然后电子邮件应该包含一个链接到处理 UUID 的视图的 URL:

from datetime import datetime
from django.http import Http404

def unsubscribe_url(request, uuid):
    uu = get_object_or_404(UnsubScribingUser, uuid=uuid)
    if uu.expires <= datetime.now():
        # unsubscribe logic
        # ...
        uu.delete()
    else:
        # too late
        # do something in that case, for example
        uu.delete()
        raise Http404

因此,我们首先检查是否存在这样的UnsubscribingUser 模型实例,在这种情况下,我们检查“会话”是否已经过期。如果没有,我们取消订阅。

因此,电子邮件包含reverse(unsubscribe_url, uuid=uu.uid) URL。过期通常是可取的,否则最终表格将存储大量 UUID,并且在白色之后,输入随机 UUID 更有可能取消订阅随机人。

【讨论】:

  • 非常感谢,这个解决方案很好,但我不确定它在我的情况下如何工作。我正在编辑我的问题以更好地解释我的需求 - 假设我有几封朋友的电子邮件,我正在向他们发送 HTML 电子邮件,每封电子邮件都有一个退订 URL,因此每封电子邮件的退订 URL 都会与其他朋友得到的不同,并且该 URL 将包含电子邮件(以某种方式),然后我将其存储在数据库中,对于您的解决方案,我必须为每个用户创建一个 UnsubscribingUser 实例,如果我将电子邮件发送到大型没有用户,只有少数退订
  • 我的用例很简单,我只需要在我的 URL 中加密我的电子邮件以取消订阅。
【解决方案2】:

用于加密。

import crypt
# To encrypt the password. This creates a password hash with a random salt.
password_hash = crypt.crypt(password)

# To check the password.
valid_password = crypt.crypt(cleartext, password_hash) == password_hash

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-03
    • 1970-01-01
    • 2012-10-03
    • 1970-01-01
    • 2011-09-29
    • 1970-01-01
    • 2017-04-01
    相关资源
    最近更新 更多