Web客戶端安全性最佳實踐

得益於HTML5,Web應用中愈來愈多的邏輯從服務器端遷移到了客戶端。於是,前端開發人員也須要更多關注安全性方面的問題。在這篇文章中,我會告訴你如何使你的應用更加安全。我會着重描述一些你可能從未據說過的技術,而不是僅僅告訴你「別忘了對用戶提交的頁面數據作轉義(escape)」。javascript

HTTP?想都別想

固然,我並不想讓你經過FTP或者普通的TCP協議來傳輸你的數據。個人意思是,若是你想讓你的用戶安全地訪問你的網站,你應該使用SSL(HTTPS)來加密你的數據傳輸。不只要加密登錄節點或者關鍵信息,而是要加密全部的數據。不然當用戶經過公用網絡訪問你的應用時,他看見的內容說不定已經被別人「黑」掉了。這就叫中間人攻擊,見下圖:php

main-in-the-middle
(譯者注:此處引用的原圖中筆誤,中間人攻擊的英文爲Man-In-The-Middle Attack)html

若是你使用SSL,全部的數據在發送以前就會被加密,即便攻擊者在網絡中截獲了數據包,他也沒有辦法查看或者篡改其中的內容。對於提高應用的安全性,這是目前爲止最重要的一步。前端

嚴格傳輸安全性標記(Strict-Transport-Security)

若是你只想經過SSL來傳輸你的數據,那麼這個HTTP頭屬性會讓你以爲很是好用。若是服務器端在響應頭中使用了這個標記(你也能夠在頁面中使用<meta>標籤,不過這樣的話就會存在一個未被加密的請求),那麼全部從客戶端到服務器端的數據都會被加密。使用方式以下:java

1
Strict-Transport-Security: max-age= 3600 ; includeSubDomains

其中的includeSubDomains屬性是可選的,你可使用它來加密當前域的子域,全部對子域的訪問也會被HTTPS加密。而其中的max-age屬性能夠設置在多長的時間範圍內(以秒爲單位)須要用SSL對頁面數據傳輸進行加密。不過惋惜的是,目前只有FirefoxChrome和Opera瀏覽器支持這個標記。json

Secure和HttpOnly屬性

還有一種方法能夠有效加強HTTP和HTTPS訪問的安全性,那就是使用Secure和HttpOnly這兩個cookie屬性。前者能確保cookie的內容只經過SSL鏈接進行傳輸;然後者正好相反。若是你以爲這二者互相矛盾,沒啥用處,那就錯了。它們告訴瀏覽器cookie的內容只能分別經過HTTP(S)協議進行訪問,從而避免了被別人輕易竊取,好比JavaScript中的document.cookie.api

經過Content-Security-Policy(CSP)標記來減小跨站腳本攻擊(XSS)的危害

若是你以爲依靠XSS過濾器可以防範全部可能的XSS攻擊,不妨先看一看這篇文章,再好好思考一下。固然,爲整個Web應用都配置上完備的防範措施也會存在一些問題,好比,可能拖累整個網站的性能。不過我還有一招。跨域

這招叫作Content-Security-Policy標記。它能讓你指定網站上全部腳本和圖片等資源的源站點。此外,它還能阻止全部內聯(inline)的腳本和樣式。即便有人在頁面評論或者回帖中嵌入了腳本標籤,這些腳本代碼也不會被執行。CSP標記通常寫在HTTP頭中(也能夠寫在HTML的<meta>標籤中),寫法以下:瀏覽器

1
Content-Security-Policy: policy

其中的policy字段表明一系列CSP屬性,下面列舉一些經常使用的屬性:安全

  • script-src– 設置能夠接受的JavaScript代碼的源站點
  • style-src– 設置能夠接受的CSS樣式代碼的源站點
  • connect-src– 定義瀏覽器能夠經過XHR、WebSocket或者EventSource訪問哪些站點
  • font-src– 設置能夠接受的字體文件的源站點
  • frame-src– 定義瀏覽器能夠經過iframe訪問哪些站點
  • img-src– 設置能夠接受的圖片的源站點
  • media-src– 設置能夠接受的音頻和視頻文件的源站點
  • object-src– 設置能夠接受的Flash和其它插件的源站點

若是沒有設置上述屬性,那麼瀏覽器默認會接受來自任何源站點的腳本和數據。不過瀏覽器的默認屬性也能經過default-src屬性來設置。其它的屬性若是沒有設置的話,就會默認採用這個屬性中設置的值。此外,還有一個叫作sandbox的屬性,它可讓瀏覽器以iframe的形式加載頁面。下面是一個CSP頭的例子:

1
Content-Security-Policy: default -src: 'self' ; script-src: https: //apis.google.com;

在這個例子中,瀏覽器只會加載源自這個Web應用所在站點的資源(默認源設置爲self),以及經過Google API服務器獲取的腳本。CSP有不少種靈活的用法,若是使用得當,能夠有效提高Web應用的安全性。

CSP的缺點

當你使用CSP的時候,有一點千萬要記住:默認狀況下,全部的內聯JavaScript腳本都不會被執行。例如:

內聯的事件監聽器:好比

1
< body onload = "main();" >

全部的javascript URL:好比

1
< a href = "javascript:doTheClick()" >

之因此這樣,是由於瀏覽器沒法區分你的內聯腳本和黑客注入的腳本。你須要經過JavaScript的addEventListener或者一些框架中相似的函數來重寫上述腳本。某種程度上來看,這也不算一件壞事,它逼你不得不分離邏輯層的代碼和展示層的代碼,而你原本就應該這麼作。此外,CSP默認還會阻止全部eval()風格的代碼的執行,包括setInterval/setTimeout中的字符串和相似於new Function(‘return false’)之類的代碼。

CSP的可用性

大部分時下流行的瀏覽器都支持CSP。Firefox、Chrome和Opera(包括手持設備上的)使用標準的CSP頭。Safari(包括iOS中的)和安卓上的Chrome使用X-WebKit-CSP頭。IE10(僅支持sandbox屬性)使用X-Content-Security-Policy頭。因此,因爲IE的支持(部分支持也是支持),你不只能夠着手使用CSP(除非你用的是Google Chrome Frame之類的東西),並且還能在各類實際的瀏覽器中運行,有效地改善Web應用的安全性。

使用跨域資源共享(Cross Origin Resource Sharing)來代替JSONP

目前因爲瀏覽器同源策略的限制,JSONP常被用於從其它服務器上獲取數據。一般的辦法是在腳本中寫一個回調函數,而後把回調函數的名字寫在請求的URL中,像下面這樣:

1
2
3
function parseData(data) {
    ...
}
1
< script src = "http://someserver.com/data?format=jsonp&callback=parseData" ></ script >

可是這樣作會有很大的安全隱患。若是你請求數據的服務器被黑了,那麼黑客就能在返回的數據中植入惡意代碼,進而竊取用戶的隱私信息。由於在瀏覽器看來,經過這種方法獲取的腳本代碼和正常的頁面代碼沒什麼區別。

正確的作法是使用跨域資源共享。它容許資源提供方在響應頭中加入一個特殊的標記,使你能經過XHR來獲取、解析並驗證數據。這樣就能避免惡意代碼在你的應用中執行。

這個方法須要在響應頭中加入的標記以下:

1
Access-Control-Allow-Origin: allowed origins

這裏能夠列舉一些能夠接受的數據源,以逗號隔開,使用通配符*來接受全部的數據源。

CORS可用性

目前全部主流的瀏覽器都支持,除了Opera Mini。

固然,更重要的是數據提供方能支持跨域資源共享,不過這就不是開發者能說了算的了。

在iframe中使用sandbox屬性

若是你使用iframe加載外部網站的內容,也別忘了它的安全問題。你能夠經過iframe的sandbox屬性來加強iframe使用的安全性。經過設置sandbox屬性,可使得iframe沒法隨意跳轉頁面,沒法執行外部腳本,沒法鎖定鼠標,沒法彈出新窗口,沒法提交表單,等等。此外頁面上若干個iframe中加載的全部內容還必須來自惟一的源,也就不能使用localStorage等有悖於同源策略的東西。固然,若是有須要的話,你也能夠經過顯式的設置來放寬限制,能夠設置的屬性以下:

  • allow-same-origin–iframe只要各自符合同源規範便可
  • allow-scripts–iframe中能夠執行JavaScript腳本
  • allow-forms–iframe中能夠提交表單
  • allow-pointer-lock–iframe中能夠鎖定鼠標
  • allow-popups– iframe中能夠彈出新窗口
  • allow-top-navigation– iframe中能夠完成頁面跳轉

可用性

目前iframe的sandbox屬性受各類主流瀏覽器支持,除了Opera Mini之外。

結束語

主要內容就是這些了。但願讀者能經過這篇文章學到一些新技術,能用於從此的項目中,更好的提高Web應用的安全性。得益於HTML5的發展,咱們能夠在Web上實現愈來愈豐富的功能。可是咱們也不能掉以輕心,由於網絡中攻擊和威脅無處不在,在敲第一行代碼以前就要好好想想安全性方面的問題。

相關文章
相關標籤/搜索