控制台显示有关Content Security策略和大量失败的GET请求的错误 [英] Console shows error about Content Security policy and lots of failed GET requests

查看:70
本文介绍了控制台显示有关Content Security策略和大量失败的GET请求的错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我实际上正在使用我的第一个Chrome扩展和,即使它顺利运行,我从 get()功能我正在使用来检索一些数据和关于代码安全性的令人讨厌的错误。



这是一个

  $。get(http://gaming.ngi.it/subscription.php?do=viewsubscription,function ){
var TDs = $('td [id * =td_threadtitle_]',data);
$(document).ready(function(){
$(#content ).html(< br />);
$ .each(TDs,function(){
//从源中删除无用的元素
$('img [ src =images / misc / tag.png]',this).remove();
$('span',this).remove(); // $('span [class =smallfont ]',这个).remove();
$('div [class =smallfont]',this).remove();
$('img [src =images / buttons / firstnew.gif]',this).attr('src','/img/icons/comment.gif');
$('a [style =font-weight:bold]' ).removeAttr(style);
//修改字符串的长度
if( $(a [id ^ ='thread_title_'],this).text()。length> 35){
$(a [id ^ ='thread_title_'],this).text($(a [id ^ ='thread_title_'],this).text()。substring(0 ,30)+[...]);
}
//修改相对于绝对值的URL,并添加target =_ newtab
$(a [id ^ ='thread_'],this).attr(' href',http://gaming.ngi.it/\"+ $(a [id ^ ='thread_'],this).attr('href'));
$(a [id ^ ='thread_'],this).attr('target',_newtab);
//将修改的HTML发送到弹出窗口
$(#content)。html($(#content)。html()+ $('div',this).wrap (< span>< / span>)。parent()。html()+< br />);
});
});
});

这里你可以从jquery中完成所有的操作后找到HTML。



老实说,我不明白为什么这些错误显示,特别是与安全性有关的错误。我的popup.html中没有使用任何内嵌代码。



Manifest.json



  {
name:NGI Little Helper,
version:0.8.5,
manifest_version:2,
描述:扩展每gli Utenti del forum games.ngi.it,
options_page:fancy-settings / source / index.html,
background:{
page:background.html
},
icons:{
16:img / logo16.png,
48:img
128:img / logo128.png
},
content_scripts:[{
matches:[*:/ /gaming.ngi.it/*],
js:[common / jquery.js,logo_changer / logo_change.js],
run_at:document_start
$ bbrowser_action:{
default_icon:img / icon.png,
default_popup:popup.html,
default_title :Visualizza订阅
},
权限:[
*://gaming.ngi.it/*
]
}

以下是一段HTML代码,将在所有操作后呈现到弹出窗口中。所有 div 与此类似,只是url更改:

  < DIV> 

< a href =http://gaming.ngi.it/showthread.php?goto=newpost&amp;t=555954id =thread_gotonew_555954target =_ newtab> < img class =inlineimgsrc =/ img / icons / comment.gifalt =转到第一个新帖子border =0>< / a>




< a href =http://gaming.ngi.it/showthread.php?goto=newpost&amp;t=555954 id =thread_title_555954target =_ newtab> [All Gamez] [Frozen Synapse] S [...]< / a>

< / div>

如果需要,我可以提供完整的源代码。

解决方案

让我们从最简单的问题开始:



拒绝执行内联脚本,因为...



$('div',this)选择所有< div> < td> 中的元素。在您提供的源代码中,可以找到以下事件处理程序:

< div class =smallfont> 
< span style =cursor:pointer onclick =window.open('member .php?u = 47995','_self')> K4raMong< / span>
< / div>

默认情况下,内容安全政策,这是禁止的。要摆脱错误,只需删除该属性,然后将其插入到文档中:

  element.removeAttribute('onclick') ; // in jQuery:$ element.removeAttr('onclick'); 



为什么加载这些图片?我没有把它们放在文档中



在jQuery / JavaScript可以操纵DOM之前,必须先解析它。在你的代码中,这个工作被隐含地在 var TDs = $(..,data)中完成。线。这个解析大约等于:

  var dummy = document.createElement('div'); // Container 
dummy.innerHTML = data;

有没有听说过预加载图像?这是缓存图像的有用功能,以便在需要时准备就绪。这可以使用(new Image).src ='...'; 完成。创建的< img> 元素不必在文档中插入。



在您的情况下,这是不希望的行为,因为这些图像在您的扩展名中查找。这是由于您的网页使用相对网址而不是绝对网址造成的。当使用相对URL时,资源的预期位置取决于当前文档的位置。



如何修复



Do 使用jQuery 。由于您正在撰写Chrome扩展程序,因此您不必担心跨浏览器的兼容性。 jQuery使用 innerHTML 技巧来解析HTML,失败了,正如我之前所展示的那样。



JavaScript有 DOMParser 对象,可以使用如下,因为Chrome 30:

  var doc =(new DOMParser).parseFromString(data,'text / HTML'); 

您可以使用 responseType 跳过手动将字符串转换为文档, code>属性,如下所示。



到达解决方案



如你所知,如果网址正确添加到清单文件中的权限部分,Chrome扩展程序中就可以进行跨站点请求。我们将使用XMLHttpRequest级别2中引入的功能,即 responseType 属性

  //获取数据
var xhr = new XMLHttpRequest();
xhr.open('GET','http://gaming.ngi.it/subscription.php?do=viewsubscription');
xhr.onload = function(){
var doc = xhr.response;
//现在,您可以使用jQuery,因为字符串已被解析。
...
};
xhr.responseType ='document'; // Chrome 18+
xhr.send();

您可以轻松地将代码重写为使用本机DOM和JavaScript而不是jQuery。大多数使用jQuery作为选择器引擎,但最常见的是也可以使用 element.querySelectorAll 。使用 var doc = xhr.response; 获取文档后,请执行以下操作:

  var TDs = doc.querySelectorAll('td [id * =td_threadtitle_]'); 
var html ='';
[] .forEach.call(TDs,function(td){
// etc等等你的工作
});

你看到 var html =''; ?这是很好的做法,不管你是否使用jQuery。 $ code> element.innerHTML + = ...; 甚至更糟糕的是$ element $($ element.html()+ ...) 在循环中。浏览器会很难再次呈现,而且您的用户注意到性能下降。


I'm actually working on my first Chrome Extension and even if it run smooth i got a lot of error from the get() function i'm using to retrieve some data and an annoying error about the security of the code.

Here's a screenshot of the console log:

Following there's the code involved:

popup.html

<!doctype html>
<html>
<head>
    <title>NGI Little Helper - Subscribes</title>
    <link rel="stylesheet" href="popup.css">
    <!-- JavaScript and HTML must be in separate files for security. -->
    <script type="text/javascript" src="common/jquery.js"></script>
    <script type="text/javascript" src="popup.js"></script>
</head>

<body>
    <h1>Topics</h1>
    <div id="content">..:: Loading ::..</div>
</body>
</html>

popup.js

This script start making a $.get() to a remote web page. The content of the variable data can be found here

$.get("http://gaming.ngi.it/subscription.php?do=viewsubscription", function(data) {
    var TDs = $('td[id*="td_threadtitle_"]', data);
    $(document).ready(function() {
        $("#content").html("<br/>");
        $.each( TDs, function() {
            //Removes useless elements from the source
            $('img[src="images/misc/tag.png"]', this).remove();
            $('span', this).remove(); //$('span[class="smallfont"]', this).remove();
            $('div[class="smallfont"]', this).remove();
            $('img[src="images/buttons/firstnew.gif"]', this).attr('src', '/img/icons/comment.gif');
            $('a[style="font-weight:bold"]', this).removeAttr("style");
            //Modify the lenght of the strings
            if ($("a[id^='thread_title_']", this).text().length > 35) {
                $("a[id^='thread_title_']", this).text( $("a[id^='thread_title_']", this).text().substring(0, 30) + " [...]" );
            }
            //Modify the URL from relative to absolute and add the target="_newtab"
            $("a[id^='thread_']", this).attr('href', "http://gaming.ngi.it/"+ $("a[id^='thread_']", this).attr('href'));
            $("a[id^='thread_']", this).attr('target', "_newtab");
            //Send the HTML modified to the popup window
            $("#content").html($("#content").html() + $('div', this).wrap("<span></span>").parent().html() +"<br/>" );
        });
    });
});

Here you can find the HTML after all the manipulation from jquery.

Honestly i cannot understand why these error show, especially the one related to the security. I've not used any inline code in my popup.html.

Manifest.json

{
    "name": "NGI Little Helper",
    "version": "0.8.5",
    "manifest_version": 2,
    "description": "Extension per gli Utenti del forum gaming.ngi.it",
    "options_page": "fancy-settings/source/index.html",
    "background": {
        "page": "background.html"
    },
    "icons": {
        "16": "img/logo16.png",
        "48": "img/logo48.png",
        "128": "img/logo128.png"
    },
    "content_scripts": [{
        "matches": ["*://gaming.ngi.it/*"],
        "js": ["common/jquery.js", "logo_changer/logo_change.js"],
        "run_at": "document_start"
    }],
    "browser_action": {
        "default_icon": "img/icon.png",
        "default_popup": "popup.html",
        "default_title": "Visualizza Subscriptions"
    },
    "permissions": [
        "*://gaming.ngi.it/*"
    ]
}

The following is a piece of HTML code that will be rendered into the popup window after all the manipulation. All the div is similar to this, just the url changes:

<div>

            <a href="http://gaming.ngi.it/showthread.php?goto=newpost&amp;t=555954" id="thread_gotonew_555954" target="_newtab"><img class="inlineimg" src="/img/icons/comment.gif" alt="Go to first new post" border="0"></a>




            <a href="http://gaming.ngi.it/showthread.php?goto=newpost&amp;t=555954" id="thread_title_555954" target="_newtab">[All Gamez] [Frozen Synapse] S [...]</a>

        </div>

If needed i can provide the full source code.

解决方案

Let's start with the easiest problem:

Refused to execute inline script because ...

$('div', this) selects all <div> elements within a <td>. In the source code you provided, the following event handler can be found:

<div class="smallfont">
    <span style="cursor:pointer" onclick="window.open('member.php?u=47995', '_self')">K4raMong</span>
</div>

By the default Content Security policy, this is forbidden. To get rid off the error, just remove the attribute before inserting it in the document:

element.removeAttribute('onclick'); // in jQuery: $element.removeAttr('onclick');

Why are these images loaded? I didn't put them in the document

Before jQuery/JavaScript can manipulate DOM, it must be parsed first. In your code, this work is implicitly done at the var TDs = $(.., data). line. This parsing is approximately equal to:

var dummy = document.createElement('div'); // Container
dummy.innerHTML = data;

Ever heard about preloading images? That is a useful feature to cache images, so that they're ready when needed. This can be done using (new Image).src='...';. The created <img> element doesn't have to be inserted in the document.

In your case, this is undesired behaviour, because these images are looked up in your extension. This is caused by the fact that your web page makes use of relative URLs, rather than absolute ones. When using relative URLs, the expected location of the resources depends on the location of the current document.

How to fix it

Do not use jQuery. Since you're writing a Chrome extension, you do not need to worry about cross-browser compatibility. jQuery uses the innerHTML trick to parse HTML, which failed, as I've previously shown.

JavaScript has the DOMParser object, which can be used as follows since Chrome 30:

var doc = (new DOMParser).parseFromString(data, 'text/html');

You can skip the manual conversion from string to document using the responseType property, as shown below.

Arriving at the solution

As you already know, cross-site requests are possible in Chrome extensions, provided that the URL is correctly added to the permissions section in the manifest file. We're going to use a feature introduced in XMLHttpRequest level 2, namely the responseType attribute.

// Fetching data
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://gaming.ngi.it/subscription.php?do=viewsubscription');
xhr.onload = function() {
    var doc = xhr.response;
    // Now, you can use jQuery, since the string has been parsed.
    ...
};
xhr.responseType = 'document'; // Chrome 18+
xhr.send();

You can easily rewrite your code to use native DOM and JavaScript instead of jQuery. Most use jQuery for the selector engine, but most often, it can also be implemented using element.querySelectorAll. After getting the document using var doc = xhr.response;, do the following:

var TDs = doc.querySelectorAll('td[id*="td_threadtitle_"]');
var html = '';
[].forEach.call(TDs, function(td) {
    // etc, etc. Do your job
});

Do you see var html = '';? That's good practice, regardless of whether you're using jQuery or not. Never do element.innerHTML += ...; or even worse $element.html($element.html() + ...); in a loop. The browser will have a hard time with rendering it over and over again, and you -as a user- notice performance degradation.

这篇关于控制台显示有关Content Security策略和大量失败的GET请求的错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆