天天看點

html實體編碼遇上js代碼

單雙引号

在js代碼中

在js中單、雙引号引起來的是字元串,如果我們要在字元串中使用單、雙引号,需要反斜杠進行轉義
let str='user\'s name';
// or
let str=" user's name";
// or
let str="she said:\"...\".";           
如果在字元串中輸出反斜杠,仍然是用反斜杠轉義,即2個反斜杠輸出1個反斜杠

在html代碼中

html标簽中,屬性值通常用雙引号引起來,也可以使用單引号或不用引号。
<input name=user />
<input name="user" />
<input name='user' />           

這3種寫法都正确,不過通常我們是選擇用雙引号引起來。

如果我們要在屬性值中使用單、雙綽号,我們不能直接寫成下面這樣

<input name=user'name />
<input name="user"name" />
<input name='user'name' />           

這些全部是錯誤的。我們要像在js中對單、雙引号轉義一樣,對屬性中的單、雙引号轉義

在html中輸出預留符号,可以使用字元實體轉義的形式,這裡有簡單介紹:

http://www.w3school.com.cn/html/html_entities.asp

。即想輸出一個雙引号可以使用

&quot;

的形式,

<input name="user&quot;name" />           

除此之外,html還支援十進制與十六進制編碼的形式輸出字元,如我們知道字元

a

ascii

碼的十進制是97 十六進制是61

是以我們在頁面

body

中輸出一個字元a,有以下3種形式

<body>
  a<!--直接輸出-->
  &#97;<!--十進制輸出-->
  &#x61;<!--十六進制輸出-->
</body>           

同樣,單雙引号也有十進制(單:39,雙:34)與十六進制(單:27,雙:22),是以我們在屬性中輸出一個單引号有2種選擇,十進制與十六進制

<input name='user&#39;name' /><!--十進制-->
<input name='user&#x27;name' /><!--十六進制-->           

而輸出一個雙引号則有3種選擇

<input name="user&quot;name" /><!--實體-->
<input name="user&#34;name" /><!--十進制-->
<input name="user&#x22;name" /><!--十六進制-->           

當js代碼遇上實體編碼

我們可以通過dom節點提供的事件寫上調用js的代碼,如點選body彈出hello這個字元串,我們可以寫成
<body onclick="alert('hello')">
click here
</body>           

如果我們的需求是就彈出一個雙引号呢?

根據前述規則,我們要寫成:

<body onclick="alert('&quot;')"><!--這裡用十進制或十六進制都可以-->
click here
</body>           

當然,alert裡的單引号也可以使用十進制或十六進制編碼

<body onclick="alert(&#34;&#39;&#34;)"><!--&#34;單引号  &#39;雙引号-->
click here
</body>           

這樣也是可以的。

是不是有點

xss

的感覺?

如果我們把彈雙引号的需求改成單引号呢?

<body onclick="alert(''')"><!--這樣html中是合法的,但js中并不合法,因為在js中,中間的單引号并沒有轉義-->
click here
</body>           

如果我們用十進制或十六進制編碼呢?

<body onclick="alert('&#34;')"><!--這樣可以嗎-->
click here
</body>           
這樣仍然是不可以的

我們要對js字元串中的單引号進行轉義,如

<body onclick="alert('\'')"><!--轉義後可正确彈出-->
click here
</body>           

<body onclick="alert('\&#34;')"><!--轉義後可正确彈出-->
click here
</body>           

前面的

onclick="alert('\'')"

看起來還正常,後面的這個

onclick="alert('\&#34;')"

就有點不直覺了。因為後面這個看上去反斜杠像在轉義

&

這1個字元,而

&

在js的字元串中并不需要轉義的。

動态輸出

如前述的alert彈出的消息,如果是一個變量控制,動态輸出呢?
<body onclick="alert('${msg}')">
click here
</body>           

那我們這個msg字元串就得注意了,從這個示例來看,這個動态的msg即出現在屬性onclick中,也出現在alert的單引号開始的字元串中。

我們要對msg中的雙引号轉成

&quot;

&#34;

&#x22;

,并對msg中單引号的前面加上一個反斜杠

\

 ?

題外話:對msg中的反斜杠需要做double處理,因為反斜杠在html屬性中并不是特殊的,但在js的字元串中是特殊的。是以正确的做法是對反斜杠及單引号前面各加上一個反斜杠

然而,你并不能保證屬性是用雙引号,alert中的字元串用的是單引号,因為可以寫成下面這樣

<body onclick='alert("${msg}")'>
click here
</body>           

?

這種情況我們要對msg中的單引号轉成

&#39

&#x27

,并對msg中雙引号前面加上一個反斜杠

\

題外話:同上

看上去要根據不同的情況做不同的處理,其實也不需要

我們隻需要對單、雙引号前面加上一個反斜杠

\

然後再對單、雙引号實體編碼即可。

在js中如果反斜杠後面跟的不需要反斜杠轉義的字元,那麼這個反斜杠是被丢棄的,是以像

var str="user\'s name";           

單引号前面多加一個反斜杠也不要緊的。

自動化處理與識别提醒

在magix項目中,由于magix-combine的支援,可識别出屬性中js代碼的部分,并自動化處理,如

<button mx-click="showName({name:'<%=name%>'})">click here</button>           

name這個變量可包含任意的單、雙引号及反斜杠。工具自動識别并處理,開發者不需要做任何事情。

而對于這樣的寫法:

<button mx-click="showName({name:'&#34;'})">click here</button>
<!-- or-->
<button mx-click="showName({name:'\&#34;'})">click here</button>           

第一種寫法其實并不正确,但第二種情況看上去又怪怪的。magix-combine工具能識别出來是否需要添加反斜杠,并自動添加處理。

第一種需要添加反斜杠,工具會自動加上,并提醒開發者這裡的寫法是不正确的。

第二種說明開發者意識到了問題所在,自己處理了,工具就不再處理也不再提醒開發者。

相關連結:

https://github.com/thx/magix https://github.com/thx/magix-combine

繼續閱讀