我想让用户有权删除他们添加到db的模型实例。在django文档中,它说允许某人从模板中删除不是一个好习惯。有没有一种安全的方法让用户从模板中单击“删除此”链接并删除该模型实例?我应该怎么做呢?
答案 0 :(得分:7)
Check out this question有关您所询问的问题的讨论。
基本上,当您通常点击页面上的链接时,浏览器会向服务器发出GET
请求以获取下一页的内容。就像有很多推动语义相关的CSS布局一样,页面请求与语义相关也很重要。使用链接删除项目的问题在于它正在向数据库中的GET
内容发出DELETE
个请求。由此产生的问题是某些搜索引擎可能会索引您的链接并意外删除内容。还有cross-site request forgeries的问题,它可以让毫无戒心的用户在不知情的情况下向网站发出命令。因此,处理此问题的正确方法是遵循以下规则:任何修改服务器状态的请求都应通过POST 进行处理。因此,而不是这样做:
<a href="{% url remove_item item.id %}">Delete Item</a>
最好这样做:
<form action='{% url remove_item %}' method='POST' id='form'>
<input type='hidden' name='action' value='delete'>
<input type='hidden' name='id' value='{{ item.id }}'>
<input type="submit" value="Delete Item">
</form>
如果您想在保留POST
的同时保留链接,则必须使用Javascript:
<a href="#" onclick="document.getElementById('form').submit(); return false;">Delete Item</a>
不好看,是的,但这是最好的。您的Django视图将执行以下操作:
def remove_item(request):
if request.method == 'POST':
## remove item
此外,正如Scott所提到的,Django有一些内置的东西可以帮助你避免我上面提到的跨站点请求伪造,因为即使你正在进行POST(稍微努力)它仍然可以做到这一点。避免这种情况的方法是在允许执行操作之前将某种令牌绑定到需要在服务器端验证的表单。查看CsrfMiddleware课程了解更多详情。它基本上会为你自动完成一些工作。
答案 1 :(得分:0)
让用户提交POST请求以删除该模型实例。通过GET请求永远不可能进行这些类型的更改,这样人们就无法在网站上无意中执行更改。
在您的视图中,检查request.user是否与该特定模型实例的作者相同。如果您真的担心,还可以检查HTTP_REFERRER是否未设置为其他站点。
此处的安全问题是跨站请求伪造。 Django提供了CsrfMiddleware,它实际上会为您的表单添加安全性以防止这种攻击。但只有当您不允许通过GET请求进行永久性更改时,它才有效。