談Web前端安全編碼 web前端安全編碼(模版篇) escape()、encodeURI()、encodeURIComponent()區別詳解

最近開發中涉及到有關輸出正確的HTML標籤這樣的問題,正好對字符編碼這塊兒多看看,以前對這個方面認識的不深,思考的確實不夠,若是下次再遇見相似的問題,若再次很多時間去調研的花,就得不償失了。javascript

就像正則表達式同樣,彷佛你知道它,可是每一次開發都須要現取查、現取測試,估計你會像我同樣,每一次都會花些意想不到的時間。html

總之,重在學習。前端

有一篇文章,這個博友已經總結的很是到位了,引入於此,看到的同窗,但願能夠多看看他作的總結:java

在web的開發的開發過程當中,前端老是在處理後端打的各類變量,變量能夠包含着中的各類各樣的字符,若是不對這些字符進行」特殊「處理的話,輕者致使頁面不正常的顯示,潛入了其餘的東西,亦即頁面掛了,或者彈出不該該彈出的東西,這些都是咱們不指望看到的,重者可能致使密碼泄露,網站的訪問量忽然猛增,服務器掛掉。web

  在前端的開發中,涉及到如下幾種語境:ajax

  1)直接顯示在頁面上, eg:<div>{%username%}</div>,<input type="text" value="{%username%}"/>正則表達式

  2)在script 標籤中,eg :<script>var test = '{%username%}';var test="{%username%}"</script>後端

  3)在頁面事件中,eg:<div onclick="alert('{%username%}')">334455</div>api

  4)在innerHTML 的語境中,eg:<div id="test"></div> <script>var test="{%username%}";document.getElementById('test').innerHTML =test; </script>安全

  5)在頁面連接的url中:eg:<a href="{%username%}"></a>

  6)提交url參數處理

  7)js 獲取url參數值的時候

下面來一個一個的分析上面提到了7種語境中的轉義狀況:

1)直接顯示在頁面上(簡稱頁面html環境中):

  爲了保證用戶的本意,完徹底全的展現在頁面上,這類主要是防止標籤的自閉合,屬性中的單引號,雙引號已經存在的狀況下不正確顯示,因此必須轉義4個字符:<,>,",'  to爲轉義的意思(下同)

  (1)<  to &lt;

  (2) > to &gt;

  (3)" to &quot;

  (4)' to &#39;

2)在script的標籤中(簡稱js環境中):

  在javascript 中 」 和' 都是表示字符串,沒有任何區別,因此若是變量中出現了這2個字符,就會影響後面不正確顯示,因此必須轉義這2個字符 ,同理,若是變量中包含\ 會將後面的'或者「給轉義掉,

變成真正的’和」,也沒有閉合,致使語法錯誤,因此這個字符也須要轉義,另外在咱們的註釋中存在/*  */ 這種形式,若是在變量中出現了 */這種字符,就會將註釋掉的部分代碼給暴漏出來,因此也要轉義/字符,

綜上所述,在script標籤中要轉義的字符爲:

  (1)'   to \'

  (2)"  to \"

  (3)\  to \\

  (4)/  to \/

3)在頁面事件中:

  這類語境涉及到了頁面html和Js 環境,要執行什麼轉義呢?究竟是先html 在js,仍是先js 再html 轉義呢?咱們來看一個例子:

  eg:<div onclick="alert('{%username%}')"></div>

    當username = " 的時候,若是是先html ,而後再js 轉義的時候,那麼就是<div onlick="alert('&qout;')"></div>   咱們拿到頁面上去執行,發現語法報錯

                若是是先js,前後在html轉義的時候,那麼就是<div onlick="alert('\&qout;')"></div>   咱們拿到頁面上去執行,成功!!

    因此結論是 先進行JS 轉義,而後再進行html 轉義,爲何是這樣呢?由於這裏它是要執行一個js函數的,若是都當作html來解析了,這裏的js函數就不會執行,也就沒有js 環境的意思了。

綜上所述,在這累語境中須要轉義的字符爲:

  (1)'   to \&#38;

  (2)"  to \&quot;

  (3)\  to \\

  (4)/  to \/

  (5)< to &lt;

  (6)< to &gt;

4) 在innerHTML環境中:

  這類語境首先是js環境中,其次是在html環境中,顯然,先進行js轉義,而後再進行html轉義,須要轉義的字符同上述3)

5)在頁面連接的url 環境中:

  這類比較複雜,url中自己涉及到不少的特殊字符,此外也會涉及到html 和js 環境中的賦值的狀況,特別注意,url 編碼和html的編碼是不同的,見後文附錄url編碼表和html編碼表

  在html 和js環境中,須要轉義的字符爲:  」  ,' ,<,>,\ ,/      

  在其餘環境中,須要轉義的字符爲:+,空格,?,=,&,#, %

  這類字符的轉義以下:

  (1)"  to %22;

  (2)' to %22;

  (3) <  to  %3C

  (4) >  to %3E

  (5) \  to %5C

  (6) / to %2F

  (7) +  to %2b

  (8)空格 to  %20

  (9)?  to  %3F

  (10)=  to  %3D

  (11)&  to %26

  (12)#  to 23

  (13) %  to %25

  爲何要轉義這些字符呢?稍微web開發的經驗同窗就知道,緣由很簡單,若是存在這些字符的話,不進行轉義,那麼咱們就會得不到咱們應該獲得的東西

引伸一點:在咱們拼接url的時候,好比將表單中的數據提取出來,用ajax的方式提交的時候,也須要對上述字符進行轉義,否則獲得的也不是想到的東西

6)提交url 參數的處理:

  1) Form  表單提交方式:不須要作任何處理,表單會依照頁面的編碼進行編碼

  2) ajax 的提交:由於ajax的提交的時候,是拼接成url的方式提交給後端的,因此必需要考慮對  +,空格,?,=,&,#, % 的轉義,一般使用 encodeURIComponent進行轉義

  關於escape,encodeURI,encodeURIComponent  這三個函數的須要的轉義字符,見後面的附件列表

7) js 獲取url參數的值的時候

  (1) 獲得url中的參數值的時候,首先必需要進行unescape的轉碼才能使用,由於url中的一些特殊字符都通過了編碼

  (2) 將url的值設置到一些參數上時,好比隱藏表單上的value值的時候(做提交refer),須要進行escape 編碼

附錄:

  1)html 編碼:http://wenku.baidu.com/view/0dbaa1dc7f1922791688e8a2.html

  2)url 編碼:http://baike.baidu.com/view/204662.htm

  3)escape,encodeURI,encodeURIComponent 的區別:http://www.alixixi.com/web/a/2008081147930.shtml

上述引文來自:web前端安全編碼(模版篇)

 

我概要一下,分爲兩類,模板(或稱爲顯示)相關,另外一類是URL相關;

1、模板(顯示)相關:

咱們要把不肯定性的後端文本變量(固然來自絕大部分來自用戶的輸入),爲了讓之正確的顯示在頁面中(也就是HTML中),或者正確的執行js代碼,咱們要對特殊字符進行轉義:

HTML環境:

< 轉義 &lt;
> 轉義 &gt;
" 轉義 &quot;
' 轉義 &#39

JS環境:

' 轉義 \'
" 轉義 \"
\ 轉義 \\
/ 轉義 \/

對應的工具函數如:

// 轉義爲HTML環境
// 主要用於innerHTML這種場景
var toSwitchForHtml = function(text){
    if (typeof text !== 'string') {
        throw new Error('The text must be a string !');
    }
    return text
            .replace(/</g,'&lt;')
            .replace(/>/g,'&gt;')
            .replace(/"/g, "&quot;")
            .replace(/'/g, "&#39;");
};

// 轉義爲JS環境
// 主要用於執行js代碼,如new Function(someStringFunctionFromServer);等
var toSwitchForJs = function(text) {
    if (typeof text !== 'string') {
        throw new Error('The text must be a string !');
    }
    return text
            .replace(/\\/g,'\\')
            .replace(/\//g,'\/')
            .replace(/"/g, "&quot;")
            .replace(/'/g, "&#39;");
};

 

2、URL相關:

主要涉及3個能夠對字符串編碼的函數,分別是:escape,encodeURI,encodeURIComponent,相應3個解碼函數:unescape,decodeURI,decodeURIComponent 。

相應的函數介紹,主要查看js api文檔便可。

這裏作了個統計表格

方法 編碼範圍 做用 備註
escape 不編碼:
ASCII字母和數字、*+-./@_
其他所有編碼爲十六進制轉義序列
在全部的計算機上讀取該字符串。
要注意,它是將須要轉義的字符轉義成UTF-16(由於JavaScript只支持16位UTF-16編碼)碼點。
關於這個轉義以後的unicode編碼方案,可參考:Unicode與JavaScript詳解
encodeURI 不編碼:
ASCII字母和數字、!’()*._~
URL特定標示符:;/?:@&=+$,#
其他所有編碼,根據URL編碼規則進行編碼
對整個URL進行編碼,而URL的特定標識符不會被轉碼。 url編碼的含義:
url編碼就是一個字符ascii碼的十六進制。不過稍微有些變更,須要在前面加上「%」。好比「\」,它的ascii碼是92,92的十六進制是5c,因此「\」的url編碼就是%5c。那麼漢字的url編碼呢?很簡單,看例子:「胡」的ascii碼是-17670,十六進制是BAFA,url編碼是「%BA%FA」。更多請參看:URL編碼
encodeURIComponent 不編碼:
ASCII字母和數字、!’()*._~
編碼:
URL特定標示符:;/?:@&=+$,#
其他所有編碼,根據URL編碼規則進行編碼
將文本字符串編碼爲一個統一資源標識符 (URI) 的一個有效組件。 請注意 encodeURIComponent() 函數 與 encodeURI() 函數的區別之處,前者假定它的參數是 URI 的一部分(好比協議、主機名、路徑或查詢字符串)。所以 encodeURIComponent() 函數將轉義用於分隔 URI 各個部分的標點符號。

根據上面的表格,咱們再來分析使用場景:

1. 當js使用數據時可使用escape,好比獲取或者設置URL中的參數值的時候(固然,約定該URL中傳遞的參數是通過unicode編碼的)

2. 進行url跳轉時能夠總體使用encodeURI。如——

document.write(encodeURI("http://abc.com/do?name=文章&name=king")); 

3.傳遞參數時須要使用encodeURIComponent,這樣組合的url纔不會被#等特殊字符截斷。如——

<script >document.write('<a href="http://passport.baidu.com/?logout&aid=7&u='+encodeURIComponent("http://cang.baidu.com/bruce42")+'">退出</a>');</script>

弄清escape、encodeURI、encodeURIComponent的內容,量並不小,須要耐心去理解、去實踐。

 

參考:

1.web前端安全編碼(模版篇)

2.escape()、encodeURI()、encodeURIComponent()區別詳解

3.URL編碼

4.HTML轉義字符

5.Unicode與JavaScript詳解

6.escape,encodeURI,encodeURIComponent方法使用

相關文章
相關標籤/搜索