通常加密也不是一个好主意,因为如果知道解密密钥,人们就可以解密所有可能的内容,而且还可以很容易地开始使用加密密钥来破解这个应用程序:如果我以某种方式发现加密密钥,我可以构造一个 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 更有可能取消订阅随机人。