如何将Django的CSRF令牌直接嵌入HTML中?

43

在我的Django应用程序中,我将HTML字符串存储在数据库中,然后将其显示在用户的主页上作为“消息”。其中一些消息包含表单,但由于不是使用模板语言编写,因此无法插入csrf令牌(从而破坏了应用程序)。

有没有办法直接从我正在编辑的Python文件中插入此令牌?我正在寻找类似以下内容的解决方法:

csrf_token = django.csrf.generate()
message = "press the button please: <form><input type='hidden' name='csrf_token' value='%s'><input type='submit' value='press here'></form>" % (csrf_token)

如果有其他在类似情景下能够起作用的解决方案,那就太好了。谢谢。

编辑: 实际上那样不会起作用,因为每个会话的令牌都不同,所以将其存储在数据库中没有什么用处。有没有一种在视图中动态加载令牌的方法?


“动态加载令牌到视图”是什么意思? - Reto Aebersold
表单以字符串形式存储在数据库中,因此如果我将令牌存储在那里,它将在加载到新会话中时无效。 如果能够从视图内部加载新的令牌,那么我就可以在呈现HTML时拦截它,插入适当的令牌,并显示工作表单。关键在于我不通过模板来插入令牌。这样清楚了吗? - ergelo
你不能只是使用csrf_protect装饰器吗? - sureshvv
3个回答

55

调用django.middleware.csrf.get_token(request)来获取CSRF令牌。


把令牌放入隐藏输入框中是否有效?因为我一直收到相同的错误,那么将此令牌放入表单的最佳方法是什么? - Francisco Peters
对我来说,解决方案是使用名称“csrfmiddlewaretoken”而不是“csrf_token”。 - Francisco Peters

51

使用它的方法是,直接在模板中使用

来自文档

<form action="" method="post">
{% csrf_token %}

你只需要包含它。


谢谢。问题在于“消息”是在视图中创建的,并且在不经过视图的情况下存储到数据库中。我将通过将表单按钮转换为链接并通过视图来解决该问题,以绕过csrf。 - ergelo
12
问题是针对不使用Django模板的情况。 - Jenia Ivanov
这对我在安装Django-CMS时解决了问题!由于某种原因,如果没有这个令牌,它将无法登录我唯一拥有的模板。很奇怪。 - MadPhysicist

12

接受的答案假设令牌已在请求对象中设置。

也许像这样的说法更好:

from django.middleware import csrf
def get_or_create_csrf_token(request):
    token = request.META.get('CSRF_COOKIE', None)
    if token is None:
        token = csrf._get_new_csrf_key()
        request.META['CSRF_COOKIE'] = token
    request.META['CSRF_COOKIE_USED'] = True
    return token

1
你不应该使用内部API,实际上在Django中_get_new_csrf_key()已经不存在了。你应该使用get_token()。 - interDist
1
如果csrf.get_token不存在令牌,它会创建一个新的令牌。 - Francisco

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接