雙引號
在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節(jié)點提供的事件寫上調用js的代碼,如點擊body彈出hello這個字符串,我們可以寫成
<body onclick="alert('hello')"> click here </body>
如果我們的需求是就彈出一個雙引號呢?
根據(jù)前述規(guī)則,我們要寫成:
<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的字符串中并不需要轉義的。
動態(tài)輸出
如前述的alert彈出的消息,如果是一個變量控制,動態(tài)輸出呢?
<body onclick="alert('${msg}')"> click here </body>
那我們這個msg字符串就得注意了,從這個示例來看,這個動態(tài)的msg即出現(xiàn)在屬性onclick中,也出現(xiàn)在alert的單引號開始的字符串中。
我們要對msg中的雙引號轉成"或"或",并對msg中單引號的前面加上一個反斜杠\ ?
題外話:對msg中的反斜杠需要做double處理,因為反斜杠在html屬性中并不是特殊的,但在js的字符串中是特殊的。因此正確的做法是對反斜杠及單引號前面各加上一個反斜杠
然而,你并不能保證屬性是用雙引號,alert中的字符串用的是單引號,因為可以寫成下面這樣
<body onclick='alert("${msg}")'> click here </body>
?
這種情況我們要對msg中的單引號轉成'或',并對msg中雙引號前面加上一個反斜杠\
題外話:同上
看上去要根據(jù)不同的情況做不同的處理,其實也不需要
我們只需要對單、雙引號前面加上一個反斜杠\然后再對單、雙引號實體編碼即可。
在js中如果反斜杠后面跟的不需要反斜杠轉義的字符,那么這個反斜杠是被丟棄的,因此像
var str="user\'s name";
單引號前面多加一個反斜杠也不要緊的。
自動化處理與識別提醒
在magix項目中,由于magix-combine的支持,可識別出屬性中js代碼的部分,并自動化處理,如
<button mx-click="showName({name:'<%=name%>'})">click here</button>
name這個變量可包含任意的單、雙引號及反斜杠。工具自動識別并處理,開發(fā)者不需要做任何事情。
而對于這樣的寫法:
<button mx-click="showName({name:'"'})">click here</button> <!-- or--> <button mx-click="showName({name:'\"'})">click here</button>
第一種寫法其實并不正確,但第二種情況看上去又怪怪的。magix-combine工具能識別出來是否需要添加反斜杠,并自動添加處理。
第一種需要添加反斜杠,工具會自動加上,并提醒開發(fā)者這里的寫法是不正確的。
第二種說明開發(fā)者意識到了問題所在,自己處理了,工具就不再處理也不再提醒開發(fā)者。
近在練習TP3.2制作個人博客時,在后臺中使用ueditor發(fā)布文章并保存在數(shù)據(jù)庫中。
如下圖,文章內容非常簡單一段文字加一個圖片,后臺中可以對文章進行修改:傳入文章ID->讀取數(shù)據(jù)庫->在ueditor中顯示,這些操作都沒有問題。
長沙蒲公英網(wǎng)絡
在前臺調用時卻發(fā)現(xiàn)文章內容未正常顯示--顯示成了HTML實體的形式。考慮到文章內容在后臺中顯示正常,區(qū)別在于有無有使編程器。所以問題可能是編輯器保存數(shù)據(jù)時可能與通常形式不一樣。
長沙蒲公英網(wǎng)絡
通過查看數(shù)據(jù)庫中文章內容保存的結果得知,編輯器將HTML標簽進行了轉義后再保存,而輸出到HTML頁面中時,標簽被轉義回單獨的字符直接顯示成了HTML代碼。這樣處理的優(yōu)點是可以避免sql注入;缺點是不能直接讀取數(shù)據(jù)。
長沙蒲公英網(wǎng)絡
知道了原因,那么問題解決起來就容易多了。1.高手可以對ueditor數(shù)據(jù)處理方式進行修改(時間成本高,可能導致sql注入的漏洞);2.可以將文章內容先讀取在ueditor中,再把ueditor中的內容顯示在頁面上(過程復雜,但簡單有效);3.讀取數(shù)據(jù)時先處理后,再在模板中進行顯示(簡單實用)。
這里簡單說明下第三種方法:在讀取數(shù)據(jù)后使用html_entity_decode函數(shù)把文章內容從 HTML 實體轉換為字符。
public function index() {
$id = I('get.id', '', 'intval');
$field = array('id', 'title', 'time', 'content', 'cid', 'click');
$blog = M('blog')->field($field)->find($id);
$blog['content'] = html_entity_decode($blog['content']);
$blog['click'] += 1;
$where = array('id' => $id);
M('blog')->where($where)->setInc('click');
$this->assign('blog', $blog);
$this->display();
}
通過以上處理后,文章內容就可以在前臺正常使用了。
長沙蒲公英網(wǎng)絡
原創(chuàng)文章鏈接:http://www.0731pgy.com/a/news/IndustryNews/430.html
*請認真填寫需求信息,我們會在24小時內與您取得聯(lián)系。