Django-如果动态url的主键发生更改,请避免错误记录

Django-如果动态url的主键发生更改,请避免错误记录,django,django-forms,django-views,Django,Django Forms,Django Views,我正在设计一个应用程序,学生可以通过调查对他们的老师进行评分 该应用程序的基本功能是为每位教师生成一个动态url,例如: 迈克老师:mywebsite.com/Teacher/1 布莱恩老师:mywebsite.com/Teacher/2 这些数字与每位教师的主键相对应。学生填写调查,在发送调查时,首先在数据库中验证之前没有发送过答案(以避免重复)。如果之前已经保存了答案,则会显示一个页面,上面写着这一点 一切正常,但如果用户(学生)执行奇怪的操作,则会出现问题。例如,当学生评分时,教师Mi

我正在设计一个应用程序,学生可以通过调查对他们的老师进行评分

该应用程序的基本功能是为每位教师生成一个动态url,例如:

  • 迈克老师:mywebsite.com/Teacher/1
  • 布莱恩老师:mywebsite.com/Teacher/2
这些数字与每位教师的主键相对应。学生填写调查,在发送调查时,首先在数据库中验证之前没有发送过答案(以避免重复)。如果之前已经保存了答案,则会显示一个页面,上面写着这一点

一切正常,但如果用户(学生)执行奇怪的操作,则会出现问题。例如,当学生评分时,教师Mike:生成的url为mywebsite.com/Teacher/rate/1,并显示一个模板,说明答案已保存。问题来了:

如果当时的人更改了url中的数字(pk),例如从1改为2,应用程序会将教师1的答案保存在教师2的记录中

澄清:如果该学生被指定为教师1、2和3,并将url中的pk更改为5,则不会出现问题,因为应用程序检测到该学生没有给该教师评分的权限。例如,问题是如果它从1改为3,因为学生有权给两个学生评分

我知道这是一种奇怪的行为。但我想找到一个办法来解决这个问题

提交答案的视图如下所示:

def send(request, user_pk):
    if not request.user.is_authenticated:
        return HttpResponseRedirect('/accounts/login/')
    else:
        #first look for the record not to exist in the DB to avoid duplicate records
        exist = Answers.objects.filter(name= request.user, teacher= user_pk ).exists()
        # if there is not then I proceed to create the record in the database
        if exist == False:
            for key, value in request.POST.items():
                if clave != 'csrfmiddlewaretoken':
                    Answers.objects.create(question=int(clave), answer_to_question=int(valor), student = request.user,teacher = int(user_pk)) 
            #then I change a record in the table of my DB where the finished evaluations are stored, from false to true.  
            actual_state= State.objects.get(student__name = request.user, teacher = user_pk)
            actual_state.finished_evaluation = True
            actual_state.save()
            return render(request,"myapp\send.html") 
        else:
            return render(request,"myapp\error.html") 

与其担心用户更改URL,我建议您添加一个检查,确保用户可以为该老师提交答案

例如,如果
教师
模型有一个
多对多
字段到
用户
,那么您可以进行筛选,以便用户只能为其教师提交答案

from django.contrib.auth.decorators import login_required
from django.shortcuts import get_object_or_404

@login_required
def send(request, user_pk):
    teacher = get_object_or_404(Teacher, students=request.user)
    exist = Answers.objects.filter(name= request.user, teacher=teacher).exists()

注意:我使用了上面的
login\u required
decorator,这样您就不必手动重定向未登录的用户。

如果学生试图将表单发布到其他老师的url,那么“正确”的结果是什么?您可以添加一个令牌(类似于csrf令牌),该令牌包含表单接受url的加密哈希。@Håken Lid最重要的是,不允许您保留该错误记录。除此之外,您还可以生成一个url,表明您试图执行的操作无效。您所说的“错误记录”是什么意思?
/teacher/1/
/teacher/2/
的格式有什么不同吗?只要你确认学生被允许为老师提交复习,那么他们怎么做又有什么关系呢?如果无法区分“虚假记录”和“真实记录”,那么似乎所有提交的表格都应该被视为有效。每个老师的表格都有差异,但我认为这不是关键。假设没有差异,调查只有一个问题:“他是一个好老师吗?”如果我更改url中的pk,我会记录老师的评分1,就像记录老师的评分2一样。这有什么问题?他们无论如何都能做到,不是吗?这就是说,在表单的隐藏字段中添加一个唯一的令牌似乎可以保护您免受这种情况的影响。例如,您可以通过以下方式生成每个师生对唯一的令牌:
hashlib.sha256(f'{student.id}{teacher.id}{settings.SECRET\u KEY}.decode()).hexdigest()
。您的建议已经在应用程序中了(我没有添加它,因为我认为它不是问题的关键,对不起,我将编辑问题)。例如,如果一名学生指定了教师1、2和3,并将url的pk更改为5,则没有问题,因为应用程序检测到该学生没有此权限。问题是学生的变化,例如从1变为3,因为学生有两个老师分配给他/她如果用户有权限给老师评分3,那么,如果用户通过干预表单提交到的URL来给教师3打分会有什么问题呢?问题不在于用户将
miweb/teacher/1
更改为
miweb/teacher/3
,因为在这种情况下,它只会重定向到教师的调查3。问题是,如果在发送教师1的调查答案后,它将url从
miweb/teacher/rate/1
更改为
miweb/teacher/rate/3
,因为它会自动在数据库中记录学生为教师1和教师3给出的答案。对不起,我不理解你最近的评论。我将删除此答案,因为它没有解决您更新的问题。我仍然认为你的做法是错误的。只要您的观点验证了用户、答案、教师组合是有效的,我就看不到添加标记以确保表单提交来自正确页面的实际好处。让我最后一次尝试让自己明白。假设你是学生。你进入
www.website.com
,页面将显示一个模板,上面写着:“你必须评估布赖恩教授和艾米教授”。点击Brian,您将进入
www.website.com/teacher/1
,调查将在此处显示。您填写调查,然后单击“发送”按钮,在该按钮中,
send
视图被激活。点击“发送”激活url
www.website.com/teacher/1/rates
,并将您关于brian的答案保存在数据库中,并显示一个模板,上面写着“您的答案已保存”