2013-03-20 50 views
2

使用最新的主幹和下劃線庫(1.0.0/1.4.4)我找不出我的模板爲什麼不像我期望的那樣轉義。下面是一個簡化版本:Backbone.js/Underscore.js:爲什麼我的模板不能轉義

M = Backbone.Model.extend({}); 
V = Backbone.View.extend({ 
    template: _.template("<%- attr %>"), 
    render: function() { 
     this.$el.html(this.template(this.model.attributes)); 
     return this; 
    } 
}); 
m = new M({attr: "<script>bad</script>"}); 
v = new V({model: m}); 
v.render(); 
console.log(v.el); 

結果:

<div><script>bad</script></div> 

這是很明顯,沒有逃脫。我驗證過的模板,作爲獨立的代碼,執行正確逃逸:

T = _.template("<%- attr %>"); 
console.log(T({attr: "<script>bad</script>"})); 

產生的

&lt;script&gt;bad&lt;&#x2F;script&gt; 

預期的結果所以某處內容越來越轉義。如果有人知道在哪裏,或者更好,如何防止它,我會非常感激。

斯蒂芬


更新:

想通了!雖然問題不是控制檯本身,的答案確實指向了我的正確方向。爲了解釋,我需要對上面的示例代碼稍加說明,以便它更準確地反映我的上下文。該上下文實際上並不是控制檯輸出,而是單元測試。我想驗證我的代碼是否正確防範XSS攻擊,所以我寫的單元測試(採用摩卡/興農/柴/應):

v.$el.text().should.equal(m.escape("attr")); 

那個測試不及格(意外),而下面測試路過(我不認爲它應該是):

v.$el.text().should.equal(m.get("attr")); 

罪魁禍首原來的元素對象上是toString()方法。該方法,即console.log()使用的方法可以使內容失效。在text()函數中,jQuery也(間接)使用該方法。

我不確定這在所有瀏覽器中都是通用的,但在我的情況下使用.innerHTML()可以避免使用toString() unescape。所以正確的方法來寫我的測試是

v.el.innerHTML().should.equal(m.escape("attr")); 
+0

http://stackoverflow.com/faq#signatures – forivall 2013-03-20 19:51:42

回答

3

我覺得你的控制檯過於「有用」,讓你困惑。如果我們仔細觀察事情,我們會看到究竟是什麼樣的詭計。我將切換到<b>而不是<script>,以避免必須將<script>分成幾塊以避免混淆jsfiddle。

考慮一下:

M = Backbone.Model.extend({}); 
V = Backbone.View.extend({ 
    template: _.template("<%- attr %>"), 
    render: function() { 
     this.$el.html(this.template(this.model.attributes)); 
     return this; 
    } 
}); 
m = new M({attr: "<b>bad</b>"}); 
v = new V({model: m}); 
v.render(); 

$('body').append(v.el); 
$('body').append($(v.el).text()).append('<br>'); 
$('body').append($(v.el).html()); 

你會看到頁面上的三件事情:

  1. 一個文字<b>bad</b>
  2. A bad以粗體顯示。
  3. 字面<b>bad</b>

這正是我們所期望看到的,如果attr轉義。

然而,你正在看控制檯。因此,讓我們來看看在控制檯以及在上述的JavaScript底部折騰了兩件事情:在我們看到的這款控制檯

console.log(v.el); 
console.log(v.el.innerHTML); 

現在:

<div><b>bad</b></div> 
&lt;b&gt;bad&lt;/b&gt; 

但在第一仔細觀察行,你應該看到<div></div>顯示爲紫色(或者控制檯用於DOM元素的任何顏色),而<b>bad</b>爲黑色(或任何您的控制檯用於純文本)。所以attr正在正確逃脫,但您的控制檯正在解碼的東西顯示之前。

演示:http://jsfiddle.net/ambiguous/5nYTd/

相關問題