我需要使用弹出窗口的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,
     ...
    });

09-27 22:17