單雙引号
在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。即想輸出一個雙引号可以使用
"
的形式,
<input name="user"name" />
除此之外,html還支援十進制與十六進制編碼的形式輸出字元,如我們知道字元
a
的
ascii
碼的十進制是97 十六進制是61
是以我們在頁面
body
中輸出一個字元a,有以下3種形式
<body>
a<!--直接輸出-->
a<!--十進制輸出-->
a<!--十六進制輸出-->
</body>
同樣,單雙引号也有十進制(單:39,雙:34)與十六進制(單:27,雙:22),是以我們在屬性中輸出一個單引号有2種選擇,十進制與十六進制
<input name='user'name' /><!--十進制-->
<input name='user'name' /><!--十六進制-->
而輸出一個雙引号則有3種選擇
<input name="user"name" /><!--實體-->
<input name="user"name" /><!--十進制-->
<input name="user"name" /><!--十六進制-->
當js代碼遇上實體編碼
我們可以通過dom節點提供的事件寫上調用js的代碼,如點選body彈出hello這個字元串,我們可以寫成
<body onclick="alert('hello')">
click here
</body>
如果我們的需求是就彈出一個雙引号呢?
根據前述規則,我們要寫成:
<body onclick="alert('"')"><!--這裡用十進制或十六進制都可以-->
click here
</body>
當然,alert裡的單引号也可以使用十進制或十六進制編碼
<body onclick="alert("'")"><!--"單引号 '雙引号-->
click here
</body>
這樣也是可以的。
是不是有點
xss
的感覺?
如果我們把彈雙引号的需求改成單引号呢?
<body onclick="alert(''')"><!--這樣html中是合法的,但js中并不合法,因為在js中,中間的單引号并沒有轉義-->
click here
</body>
如果我們用十進制或十六進制編碼呢?
<body onclick="alert('"')"><!--這樣可以嗎-->
click here
</body>
這樣仍然是不可以的
我們要對js字元串中的單引号進行轉義,如
<body onclick="alert('\'')"><!--轉義後可正确彈出-->
click here
</body>
或
<body onclick="alert('\"')"><!--轉義後可正确彈出-->
click here
</body>
前面的
onclick="alert('\'')"
看起來還正常,後面的這個
onclick="alert('\"')"
就有點不直覺了。因為後面這個看上去反斜杠像在轉義
&
這1個字元,而
&
在js的字元串中并不需要轉義的。
動态輸出
如前述的alert彈出的消息,如果是一個變量控制,動态輸出呢?
<body onclick="alert('${msg}')">
click here
</body>
那我們這個msg字元串就得注意了,從這個示例來看,這個動态的msg即出現在屬性onclick中,也出現在alert的單引号開始的字元串中。
我們要對msg中的雙引号轉成
"
"
"
,并對msg中單引号的前面加上一個反斜杠
\
?
題外話:對msg中的反斜杠需要做double處理,因為反斜杠在html屬性中并不是特殊的,但在js的字元串中是特殊的。是以正确的做法是對反斜杠及單引号前面各加上一個反斜杠
然而,你并不能保證屬性是用雙引号,alert中的字元串用的是單引号,因為可以寫成下面這樣
<body onclick='alert("${msg}")'>
click here
</body>
?
這種情況我們要對msg中的單引号轉成
'
'
,并對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:'"'})">click here</button>
<!-- or-->
<button mx-click="showName({name:'\"'})">click here</button>
第一種寫法其實并不正确,但第二種情況看上去又怪怪的。magix-combine工具能識别出來是否需要添加反斜杠,并自動添加處理。
第一種需要添加反斜杠,工具會自動加上,并提醒開發者這裡的寫法是不正确的。
第二種說明開發者意識到了問題所在,自己處理了,工具就不再處理也不再提醒開發者。
相關連結:
https://github.com/thx/magix https://github.com/thx/magix-combine