我需要使用弹出窗口的js将一些数据发布到django服务器。由于csrf,我应该在cookie中使用csrftoken发布数据,我该如何获取cookie中的值。我尝试了以下不起作用的方法:
document.cookie
chrome.cookies.get({url: "chrome-extension://igmgfjnbghncmhbobdpjblokohejackc", name: "csrftoken"}, function(cookie){})
请求信息:
Request Method:POST
Status Code:403 FORBIDDEN
Request Headersview source
Accept:*/*
Accept-Encoding:gzip, deflate
Accept-Language:zh-CN,zh;q=0.8
Connection:keep-alive
Content-Length:3
Content-Type:application/x-www-form-urlencoded; charset=UTF-8
Cookie:csrftoken=V6OTh2NdwnomqLbkfh24qRwT8C0kESIV
Host:127.0.0.1:8000
Origin:chrome-extension://igmgfjnbghncmhbobdpjblokohejackc
User-Agent:Mozilla/5.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/600.1.3 (KHTML, like Gecko) Version/8.0 Mobile/12A4345d Safari/600.1.4
X-CSRFToken:null
最佳答案
您不能从任何域访问csrftoken cookie,但只能从生成该域的域访问。因此,如果要在扩展程序中使用它,则必须阅读csrftoken并保存它。
在我的情况下,当令牌不存在时,它不会引起任何错误,但是一旦我登录服务器,就设置了csrftoken,并且无法从任何其他域中检索它,从而导致403错误在同一域中未生成的任何请求。
要修复它,首先,我必须在登录时从域中读取Cookie并将其保存到chrome存储。首先,我需要适当的权限(请注意,在使用background / background.js的情况下,您可以根据需要切换到popup / popup.js)
manifest.json
...,
"background": {
"scripts": ["jquery-1.11.1.min.js","background.js"],
"persistent": false
},
"permissions": ["tabs", "<all_urls>", "storage", "webNavigation"],
"content_scripts":[
{
"matches":["yourDomain"],
"js": ["jquery-1.11.1.min.js", "readCSRFToken.js"]
}],...
现在,这个小脚本将读取我们需要的cookie(如果存在)并将其发送到我们的扩展程序。如果要确保使用正确的CSRF令牌,可以在发送cookie之前检查主机名。
readCSRFToken.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]);
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
csrftoken = getCookie("csrftoken");
if ( csrftoken ){
chrome.runtime.sendMessage({action:"setCsrfToken", csrftoken:csrftoken}, function(){});
}
在扩展代码中,我们添加了一个侦听器,该侦听器在注入代码发送时将csrf令牌保存在chrome存储中。
还有一个webNavigation.onComplete,它将在每次加载页面时从存储中读取令牌。
background.js
csrftoken = null;
chrome.webNavigation.onCompleted.addListener(function(details) {
if ( details.frameId == 0 ){
chrome.storage.sync.get(["csrftoken"], function(storage){
csrftoken = storage.csrftoken;
});}
}
);
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
switch ( request.action ){
case "setCsrfToken":{
chrome.storage.sync.set({'csrftoken': request.csrftoken}, function() {});
}
break;
}
});
最后,我们存储了一个csrftoken变量,我们应该可以使用它来设置“ X-CSRFToken”标头,以使我们的AJAX请求在扩展中使用时能够正常工作。
...
var headers = {}
if ( csrftoken ) headers["X-CSRFToken"] = csrftoken;
$.ajax({
dataType: 'json',
headers: headers,
...
});