use*_*739 4 ajax post csrf django-views django-csrf
我遇到了一个奇怪的问题。我正在编写一个简单的小应用程序,需要将一些内容发布回 django 视图。我正在遵循此处的指南:https : //docs.djangoproject.com/en/1.7/ref/contrib/csrf/设置 ajax 标头并在我的 js 中包含以下代码:
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
console.log(csrftoken)
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
Run Code Online (Sandbox Code Playgroud)
我的 html 中有一个带有代码的表单:
<form onsubmit="return false;">
{% csrf_token %}
<input type="text" id="map-id-input"/>
<button id="map-id-btn" class='btn btn-default custom-btn'>
Go
</button>
</form>
Run Code Online (Sandbox Code Playgroud)
我还有一段 js 代码,当点击上面的按钮时运行:
$(function() {
$("#map-id-btn").click(function() {
checkMapID();
})
})
function checkMapID() {
var mapId = $("#map-id-input").val();
$.ajax({
url: "check_map_id/",
type: "POST",
dataType: "json",
data: {
csrfmiddlewaretoken: csrftoken,
map_id: mapId,
},
success: function(status_dict) {
if (status_dict.status === 1) {
$("#status").html("Valid map ID <br> Loading Data...")
window.location = status_dict.url;
}
else {
$("#status").html("Invalid map ID. Please try again, or contact ...")
}
},
error: function(result) {
console.log(result)
}
});
}
Run Code Online (Sandbox Code Playgroud)
我所有的 Javacript 都在一个文件中,放在我模板的顶部。
捕获 url 'check_map_id/' 的视图是:
@ensure_csrf_cookie
def check_map_id(request):
map_id = request.POST['map_id']
if map_id not in GEOJSON_LOOKUP.keys():
status = json.dumps({
'status': 0,
'url': '',
})
return HttpResponse(status, content_type="application/json")
else:
status = json.dumps({
'status': 1,
'url': reverse('map', args=(map_id,)),
})
return HttpResponse(status, content_type="application/json")
Run Code Online (Sandbox Code Playgroud)
现在,当我使用 firefox 在本地机器上运行该应用程序时,我会得到一个有效的 csrf 令牌被打印到控制台。如果我在 chrome 或 IE 的本地机器上启动应用程序,我会打印一个空值。同样的行为在现场网站上也得到了回应。我正在使用 linux (mint),奇怪的是,如果我在 windows 机器上的 firefox 中启动应用程序,它也会在 firefox 中返回 null。这里正在发生一些奇怪的事情!有任何想法吗?我似乎完全按照 django 文档的建议去做。
更新:我将@ensure_csrf_cookie 添加到我的索引视图中,现在我在本地机器上的两个浏览器上都打印了一个令牌。但是,该代码在我的实时服务器上不起作用。如果我在我的 js 中添加一些随机的 console.logs,它会显示在实时服务器上,因此代码正在运行。我真的很茫然。
UPDATE2:所以我已经确定问题是在我的实时站点上,没有设置 document.cookie 属性。我猜 csrftoken="..." cookie 是由 django 设置的。它似乎是在我的本地机器上设置它,但不是在我的实时站点上。代码是相同的:/。这到底是怎么回事?!
好的。我发现了问题!这是一个简单的情况,首先没有将 csrf 令牌实际发送到 html 页面。我专注于 ajax 调用,这实际上是正确的。
我更改了实际呈现违规表单所在页面的视图:
@ensure_csrf_cookie
def index(request):
context = RequestContext(request)
return render_to_response('vis_it_app/index.html', context)
Run Code Online (Sandbox Code Playgroud)
这里的关键是“RequestContext”,默认情况下,它也会发送 csfr 令牌。那是一个使命...
所以总结一下。为了使这项工作。
通过使用 RequestContext 和 @ensure_csrf_cookie 确保 csrf 令牌实际发送到您打算使用它的页面
确保 {% csrf_token %} 位于您的表单中
将此处找到的 AJAX 特定代码添加到您的页面 JavaScript :https : //docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax
确保通过以下方式将中间件令牌与 ajax 数据一起发送回:
$.ajax({ url: "...", type: "POST", dataType: "...", data: { csrfmiddlewaretoken: csrftoken, ... },
那应该这样做。
| 归档时间: |
|
| 查看次数: |
2526 次 |
| 最近记录: |