如何在 Django 中使用用户的 unique_id 和令牌发送 url?

sti*_*ing 1 django django-csrf

我为大学创建了一个 Django 应用程序(“监考管理系统”)。我没有包含任何登录授权,因为它只会被大学管理员使用。在这个应用程序中,我还剩下一项任务,我必须通过邮件为数据库中的所有用户发送可用性表格,要求他们填写表格,无论他们当天是否有空,根据他们的回复我必须存储它们在数据库中的可用性状态。如何通过邮件发送表格?或者我应该向他们发送表格的链接?如果我必须发送链接,如何仅通过更改他们获得的链接来防止一个用户访问其他用户的表单,知道如何添加令牌及其唯一 id 吗?

Deb*_*dra 11

发送带有唯一令牌的电子邮件。

生成令牌:

使用用户的字段作为盐生成随机令牌。可以是一个或多个字段,如名字、姓氏、用户 ID 等。似乎您没有庞大的用户群,并且出现重复令牌的可能性较小。

如何生成令牌?

有很多包可以帮助您生成随机令牌。按我的经验,我发现uuidsecretshashlib乐于助人,当然这些都是建立在图书馆蟒。

例子:

# recommended, uuid guarantees uniqueness.

>>> import uuid
>>> print(uuid.uuid4().hex)
'772d4c80-3668-4980-a014-aae59e34b9b9'

# others way, some sort of salt combination

>>> import secrets, hashlib
>>> first_name = user.first_name  # pull user first name, a salt.
>>> salt = secrets.token_hex(8) + first_name
>>> hashlib.sha256(salt.encode('utf-8')).hexdigest()
'f8b2e14fe3496de336017687089fb3c49bcab889ac80545fc087289c5b1a3850'
Run Code Online (Sandbox Code Playgroud)

生成随机令牌非常简单,接下来。

现在将您的随机令牌存储在与用户相关的数据库中,根据所使用的令牌生成方法,我们可能很少有重复令牌的可能性。确保定期清理过期的令牌。

当您使用盐组合方法时,我建议您检查令牌是否存在,如果存在则重新生成。

示例唯一令牌模型:

from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone

class UserUniqueToken(models.Model):
    user_id = models.ForeignKey(User, on_delete=models.CASCADE)
    token = models.CharField(max_length=100)
    datetime = models.DateField(default=timezone.now)  # for token expiration
Run Code Online (Sandbox Code Playgroud)

如何检查令牌有效性?

views.py

from .models import UserUniqueToken
from django.shortcuts import get_object_or_404
from django.contrib.auth.decorators import login_required
from django.utils import timezone
from datetime import timedelta

@login_required
def user_form(request, token):
    user_token = get_object_or_404(UserUniqueToken, token=token)  # get object or throw 404
    if not user_token.user_id == request.user.id:  # check token belongs to the user 
        # token does not belongs to the current user, do something 
    time_now = timezone.now()  # current time
    if user_token.datetime > (time_now - timedelta(hours=2)):  # check if stored time exceeds 2 hours
          # do something with expired token here.
    return render(.............)  # successful, render or throw success response
Run Code Online (Sandbox Code Playgroud)

urls.py

from .views import user_form

urlpatterns = [
        path('form/<string:token>', user_form, name='user-form'),
]
Run Code Online (Sandbox Code Playgroud)

您还可以考虑以天为间隔删除过期的令牌,因为过期的令牌会随着时间而过时。