在<script>块</script>中转义JavaScript字符串文字中的HTML实体

时间:2012-01-05 20:05:38

标签: javascript html escaping

一方面如果我有

<script>
var s = 'Hello </script>';
console.log(s);
</script>

浏览器会提前终止<script>块,基本上我搞砸了页面。

另一方面,字符串的值可能来自用户(例如,通过之前提交的表单,现在字符串最终作为文字插入<script>块),所以你可以期待该字符串中的任何内容,包括恶意形成的标记。现在,如果我在生成页面时使用htmlentities()转义字符串文字,则s的值将按字面包含转义的实体,即s将输出

Hello &lt;/script&gt;

在这种情况下不是所希望的行为。

<script>块中正确转义JS字符串的一种方法是,如果它在左尖括号之后,或者只是总是从斜杠中转义,就会转义斜杠,即

var s = 'Hello <\/script>';

这似乎工作正常。

然后是HTML事件处理程序中的JS代码问题,也可以很容易地解决,例如。

<div onClick="alert('Hello ">')"></div>

最初看起来有效,但在大多数(或所有?)浏览器中都会中断。这显然需要完整的HTML实体编码。

我的问题是:正确覆盖上述所有情况的最佳/标准做法是什么 - 即脚本块中的JS,事件处理程序中的JS - 如果您的JS代码可以部分地在服务器端生成并且可能包含恶意数据?

5 个答案:

答案 0 :(得分:40)

以下字符可能干扰HTML或Javascript解析器,并应在字符串文字中进行转义:<, >, ", ', \,&

在使用转义字符的脚本块中,如您所知,有效。连接方法(</scr' + 'ipt>')可能难以阅读。

var s = 'Hello <\/script>';

对于HTML中的内联Javascript,您可以使用实体:

<div onClick="alert('Hello &quot;>')">click me</div>

演示:http://jsfiddle.net/ThinkingStiff/67RZH/

适用于<script>块和内联Javascript的方法是\uxxxx,其中xxxx是十六进制字符代码。

  • < - \u003c
  • > - \u003e
  • " - \u0022
  • ' - \u0027
  • \ - \u005c
  • & - \u0026

演示:http://jsfiddle.net/ThinkingStiff/Vz8n7/

HTML:

<div onClick="alert('Hello \u0022>')">click me</div>

<script>
    var s = 'Hello \u003c/script\u003e';
alert( s );
</script>   

答案 1 :(得分:2)

(编辑 - 不知何故没注意到你已经在你的问题中提到了斜线逃逸...)

好的,所以你知道如何逃避斜线。

在内联事件处理程序中,您不能在文字中使用边界字符,因此请使用另一个:

<div onClick='alert("Hello \"")'>test</div>

但这有助于让你的生活变得困难。只是不要使用内联事件处理程序!或者,如果你绝对必须,那么让他们调用其他地方定义的函数。

一般来说,服务器端代码编写javascript的原因很少。不要从服务器生成脚本 - 而是将数据传递给预先编写的脚本。

(原创)

你可以使用反斜杠(不是特殊的转义字符)来转义JS字符串文字中的任何内容:

var s = 'Hello <\/script>';

这也具有使其不被解释为html的积极效果。因此,您可以用“\ /”替换“/”,以免产生不良影响。

但是,一般情况下,我担心您会在javascript中将用户提交的数据嵌入为字符串文字。你在服务器上生成javascript代码吗?为什么不直接将数据作为JSON或HTML“数据”属性传递?

答案 2 :(得分:2)

我认为最好的做法是首先避免使用内联JS

将JS代码放在单独的文件中,并将其包含在src属性

<script src="path/to/file.js"></script>

并使用它从内部设置事件处理程序,而不是将它们放在HTML中。

//jquery example
$('div.something').on('click', function(){
    alert('Hello>');
})

答案 3 :(得分:2)

以下是我的表现方式:

&#13;
&#13;
function encode(r){
return r.replace(/[\x26\x0A\<>'"]/g,function(r){return"&#"+r.charCodeAt(0)+";"})
}

var myString='Encode HTML entities!\n"Safe" escape <script></'+'script> & other tags!';

test.value=encode(myString);

testing.innerHTML=encode(myString);

/*************
* \x26 is &ampersand (it has to be first),
* \x0A is newline,
*************/
&#13;
<textarea id=test rows="9" cols="55"></textarea>

<div id="testing">www.WHAK.com</div>
&#13;
&#13;
&#13;

答案 4 :(得分:-2)

大多数人都使用这个技巧:

var s = 'Hello </scr' + 'ipt>';