一方面如果我有
<script>
var s = 'Hello </script>';
console.log(s);
</script>
浏览器会提前终止<script>
块,基本上我搞砸了页面。
另一方面,字符串的值可能来自用户(例如,通过之前提交的表单,现在字符串最终作为文字插入<script>
块),所以你可以期待该字符串中的任何内容,包括恶意形成的标记。现在,如果我在生成页面时使用htmlentities()转义字符串文字,则s的值将按字面包含转义的实体,即s将输出
Hello </script>
在这种情况下不是所希望的行为。
在<script>
块中正确转义JS字符串的一种方法是,如果它在左尖括号之后,或者只是总是从斜杠中转义,就会转义斜杠,即
var s = 'Hello <\/script>';
这似乎工作正常。
然后是HTML事件处理程序中的JS代码问题,也可以很容易地解决,例如。
<div onClick="alert('Hello ">')"></div>
最初看起来有效,但在大多数(或所有?)浏览器中都会中断。这显然需要完整的HTML实体编码。
我的问题是:正确覆盖上述所有情况的最佳/标准做法是什么 - 即脚本块中的JS,事件处理程序中的JS - 如果您的JS代码可以部分地在服务器端生成并且可能包含恶意数据?
答案 0 :(得分:40)
以下字符可能干扰HTML或Javascript解析器,并应在字符串文字中进行转义:<, >, ", ', \,
和&
。
在使用转义字符的脚本块中,如您所知,有效。连接方法(</scr' + 'ipt>'
)可能难以阅读。
var s = 'Hello <\/script>';
对于HTML中的内联Javascript,您可以使用实体:
<div onClick="alert('Hello ">')">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)
以下是我的表现方式:
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 &ersand (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;
答案 4 :(得分:-2)
大多数人都使用这个技巧:
var s = 'Hello </scr' + 'ipt>';