CORS 和 CSRF 修煉寶典

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"CORS 和 CSRF 太容易混淆了,看完本文,你就清楚了。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"一、CORS 和 CSRF 區別"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"先看下圖:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/35/358704d841fa24ae40955725f3412ac9.png","alt":"CORS 和 CSRF 區別","title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"兩者概念完全不同,另外常常我們也會看到 XSS ,這裏一起介紹:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"1","normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"CORS"},{"type":"text","text":" : Cross Origin Resourse-Sharing 跨站資源共享"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"2","normalizeStart":"2"},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"CSRF"},{"type":"text","text":" : Cross-Site Request Forgery 跨站請求僞造"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"3","normalizeStart":"3"},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"XSS"},{"type":"text","text":" : Cross Site Scrit 跨站腳本攻擊(爲與 CSS 區別,所以在安全領域叫 XSS)"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"二、CORS"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"1. 概念"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"跨來源資源共享(CORS),亦譯爲跨域資源共享,是一份瀏覽器技術的規範,提供了 Web 服務從不同網域傳來沙盒腳本的方法,以避開瀏覽器的同源策略,是 JSONP 模式的現代版。與 JSONP 不同,CORS 除了 GET 請求方法以外也支持其他的 HTTP 請求。用 CORS 可以讓網頁設計師用一般的 XMLHttpRequest,這種方式的錯誤處理比 JSONP 要來的好。另一方面,JSONP 可以在不支持 CORS 的老舊瀏覽器上運作。現代的瀏覽器都支持 CORS。"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"—— "},{"type":"link","attrs":{"href":"https://zh.wikipedia.org/wiki/%E8%B7%A8%E4%BE%86%E6%BA%90%E8%B3%87%E6%BA%90%E5%85%B1%E4%BA%AB","title":""},"content":[{"type":"text","text":"維基百科"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"核心知識:"},{"type":"text","text":" CORS是一個W3C標準,它允許瀏覽器向跨源服務器,發出"},{"type":"codeinline","content":[{"type":"text","text":"XMLHttpRequest"}]},{"type":"text","text":" 請求,從而克服 AJAX 只能同源使用的限制。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"因此,實現 CORS 通信的關鍵是服務器。只要服務器實現了 CORS 接口,就可以跨源通信,即爲了解決"},{"type":"text","marks":[{"type":"strong"}],"text":"跨域問題"},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"2. CORS 請求類型"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"瀏覽器將 CORS 請求分成兩類:"},{"type":"text","marks":[{"type":"strong"}],"text":"簡單請求"},{"type":"text","text":"(simple request)和"},{"type":"text","marks":[{"type":"strong"}],"text":"非簡單請求"},{"type":"text","text":"(not-so-simple request)。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"簡單請求"},{"type":"text","text":"一般包括下面兩種情況:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/e7/e71c791ee49c991a7279d375885a519a.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"凡是不同時滿足上面兩個條件,就屬於"},{"type":"text","marks":[{"type":"strong"}],"text":"非簡單請求"},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"3. 簡單請求的 CORS 流程"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當瀏覽器發現我們的 AJAX 請求是個"},{"type":"text","marks":[{"type":"strong"}],"text":"簡單請求"},{"type":"text","text":",便會自動在"},{"type":"text","marks":[{"type":"strong"}],"text":"頭信息"},{"type":"text","text":"中,增加一個 "},{"type":"codeinline","content":[{"type":"text","text":"Origin"}]},{"type":"text","text":" 字段。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Origin"}]},{"type":"text","text":" 字段用來說明本次請求的來源(包括"},{"type":"text","marks":[{"type":"strong"}],"text":"協議"},{"type":"text","text":" + "},{"type":"text","marks":[{"type":"strong"}],"text":"域名"},{"type":"text","text":" + "},{"type":"text","marks":[{"type":"strong"}],"text":"端口號"},{"type":"text","text":"),服務端根據這個值來決定是否同意此次請求。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/d3/d3b55b23176e39da61ee6087b77ddb3c.png","alt":"簡單請求的 CORS 流程","title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當 "},{"type":"codeinline","content":[{"type":"text","text":"Origin"}]},{"type":"text","text":" 指定的源不在許可範圍,服務器會返回一個正常的 HTTP 迴應,但瀏覽器會在響應頭中發現 "},{"type":"codeinline","content":[{"type":"text","text":"Access-Control-Allow-Origin"}]},{"type":"text","text":" 字段,便拋出異常。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當 "},{"type":"codeinline","content":[{"type":"text","text":"Origin"}]},{"type":"text","text":" 指定的源在許可範圍,服務器返回的響應頭中會多出幾個頭信息字段:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/5e/5e51291b58585e2edfe2f521230fb8c9.png","alt":"簡單請求的 CORS 流程","title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"除了上面圖中的頭信息,一般會有以下三個相關頭信息:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"1","normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Access-Control-Allow-Origin"}]}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"該字段是必須的。表示許可範圍的域名,通常有兩種值:"},{"type":"text","marks":[{"type":"strong"}],"text":"請求時 Origin 字段的值"},{"type":"text","text":"或者 "},{"type":"codeinline","content":[{"type":"text","text":"*"}]},{"type":"text","text":"(星號)表示任意域名。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"2","normalizeStart":"2"},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Access-Control-Allow-Credentials"}]}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"該字段可選。布爾值,表示是否允許在 CORS 請求之中發送 "},{"type":"codeinline","content":[{"type":"text","text":"Cookie"}]},{"type":"text","text":" 。若不攜帶 "},{"type":"codeinline","content":[{"type":"text","text":"Cookie"}]},{"type":"text","text":" 則不需要設置該字段。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當設置爲 "},{"type":"codeinline","content":[{"type":"text","text":"true"}]},{"type":"text","text":" 則 "},{"type":"codeinline","content":[{"type":"text","text":"Cookie"}]},{"type":"text","text":" 包含在請求中,一起發送給服務器。還需要在 AJAX 請求中開啓 "},{"type":"codeinline","content":[{"type":"text","text":"withCredentials"}]},{"type":"text","text":" 屬性,否則瀏覽器也不會發送 "},{"type":"codeinline","content":[{"type":"text","text":"Cookie"}]},{"type":"text","text":" 。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"js"},"content":[{"type":"text","text":"let xhr = new XMLHttpRequest();\nxhr.withCredentials = true;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"注意:"},{"type":"text","text":" 如果前端設置 "},{"type":"codeinline","content":[{"type":"text","text":"Access-Control-Allow-Credentials"}]},{"type":"text","text":" 爲 "},{"type":"codeinline","content":[{"type":"text","text":"true"}]},{"type":"text","text":" 來攜帶 Cookie 發起請求,則服務端 "},{"type":"codeinline","content":[{"type":"text","text":"Access-Control-Allow-Origin"}]},{"type":"text","text":" 不能設置爲 "},{"type":"codeinline","content":[{"type":"text","text":"*"}]},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"3","normalizeStart":"3"},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Access-Control-Expose-Headers"}]}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"該字段可選。可以設置需要獲取的字段。因爲默認 CORS 請求時,"},{"type":"codeinline","content":[{"type":"text","text":"XMLHttpRequest"}]},{"type":"text","text":" 對象的"},{"type":"codeinline","content":[{"type":"text","text":"getResponseHeader()"}]},{"type":"text","text":"方法只能拿到以下 6 個基本字段:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Cache-Control"}]},{"type":"text","text":"、"},{"type":"codeinline","content":[{"type":"text","text":"Content-Language"}]},{"type":"text","text":"、"},{"type":"codeinline","content":[{"type":"text","text":"Content-Type"}]},{"type":"text","text":"、"},{"type":"codeinline","content":[{"type":"text","text":"Expires"}]},{"type":"text","text":"、"},{"type":"codeinline","content":[{"type":"text","text":"Last-Modified"}]},{"type":"text","text":"、"},{"type":"codeinline","content":[{"type":"text","text":"Pragma"}]},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"4. 非簡單請求的 CORS 流程"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"非簡單請求"},{"type":"text","text":"情況如:請求方法是 "},{"type":"text","marks":[{"type":"strong"}],"text":"PUT"},{"type":"text","text":" / "},{"type":"text","marks":[{"type":"strong"}],"text":"DELETE"},{"type":"text","text":" 或者 "},{"type":"codeinline","content":[{"type":"text","text":"Content-Type:application/json"}]},{"type":"text","text":" 類型的請求。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在非簡單請求發出 CORS 請求時,會在正式通信之前增加一次 "},{"type":"text","marks":[{"type":"strong"}],"text":"“預檢”請求(OPTIONS方法)"},{"type":"text","text":",來詢問服務器,本次請求的域名是否在許可名單中,以及使用哪些頭信息。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當 "},{"type":"text","marks":[{"type":"strong"}],"text":"“預檢”請求"},{"type":"text","text":" 通過以後,纔會正式發起 AJAX 請求,否則報錯。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"4.1 預檢請求"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"http"},"content":[{"type":"text","text":"OPTIONS /cors HTTP/1.1\nOrigin: http://api.bob.com\nAccess-Control-Request-Method: PUT\nAccess-Control-Request-Headers: X-Custom-Header\nUser-Agent: Mozilla/5.0...\n..."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"“預檢”請求"},{"type":"text","text":" 信息中包含兩個特殊字段:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"1","normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Access-Control-Request-Method"}]}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"該字段是必須的,用來列出瀏覽器的 CORS 請求會用到哪些 HTTP 方法,上例是 "},{"type":"codeinline","content":[{"type":"text","text":"PUT"}]},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"2","normalizeStart":"2"},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Access-Control-Request-Headers"}]}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"指定瀏覽器 CORS 請求額外發送的頭信息字段,上例是 "},{"type":"codeinline","content":[{"type":"text","text":"X-Custom-Header"}]},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"4.2 預檢響應"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"http"},"content":[{"type":"text","text":"HTTP/1.1 200 OK\nAccess-Control-Allow-Origin: http://api.bob.com\nAccess-Control-Allow-Methods: GET, POST, PUT\nAccess-Control-Allow-Headers: X-Custom-Header\nContent-Type: text/html; charset=utf-8\nConnection: Keep-Alive\n..."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當預檢請求"},{"type":"text","marks":[{"type":"strong"}],"text":"通過"},{"type":"text","text":"以後,在預檢響應頭中,會返回 "},{"type":"codeinline","content":[{"type":"text","text":"Access-Control-Allow-"}]},{"type":"text","text":" 開頭的信息,其中 "},{"type":"codeinline","content":[{"type":"text","text":"Access-Control-Allow-Origin"}]},{"type":"text","text":" 表示許可範圍,值也可以是 "},{"type":"codeinline","content":[{"type":"text","text":"*"}]},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當預檢請求"},{"type":"text","marks":[{"type":"strong"}],"text":"拒絕"},{"type":"text","text":"以後,在預檢響應頭中,不會返回 "},{"type":"codeinline","content":[{"type":"text","text":"Access-Control-Allow-"}]},{"type":"text","text":" 開頭的信息,並在控制檯輸出錯誤信息。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"三、CSRF"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"1. 概念"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"跨站請求僞造(英語:Cross-site request forgery),也被稱爲 one-click attack 或者 session riding,通常縮寫爲 CSRF 或者 XSRF, 是一種挾制用戶在當前已登錄的Web應用程序上執行非本意的操作的攻擊方法。跟跨網站腳本(XSS)相比,XSS 利用的是用戶對指定網站的信任,CSRF 利用的是網站對用戶網頁瀏覽器的信任。"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"—— "},{"type":"link","attrs":{"href":"https://zh.wikipedia.org/wiki/%E8%B7%A8%E7%AB%99%E8%AF%B7%E6%B1%82%E4%BC%AA%E9%80%A0","title":""},"content":[{"type":"text","text":"維基百科"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"核心知識:"},{"type":"text","text":" 跨站點請求僞造請求。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"簡單理解:"},{"type":"text","text":" 攻擊者盜用你的身份,以你的名義發送惡意請求。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"常見場景:以你名義發送郵件,發消息,盜取你的賬號,甚至於購買商品,虛擬貨幣轉賬等等。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"造成影響:個人隱私泄露以及財產安全。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"2. CSRF 攻擊流程"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/8d/8d3d30a381f0e9c6a6eea4a0cfc8a101.png","alt":"CSRF 攻擊流程","title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"上面描述了 CSRF 攻擊的流程,其中受害者完成兩個步驟:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"1","normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"登錄受信任網站 A ,並在本地生成保存Cookie;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"在不登出 A 情況下,訪問病毒網站 B;"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可以理解爲:若以上兩個步驟沒有都完成,則不會受到 CSRF 攻擊。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"3. 服務端防禦 CSRF 攻擊"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"服務端防禦的方式有很多,思想類似,都是在客戶端頁面增加"},{"type":"text","marks":[{"type":"strong"}],"text":"僞隨機數"},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"3.1 Cookie Hashing(所有表單都包含同一個僞隨機數)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"最簡單有效方式,因爲攻擊者理論上無法獲取第三方的Cookie,所以表單數據僞造失敗。以 php 代碼爲例:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"php"},"content":[{"type":"text","text":""}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在表單裏增加Hash值,以認證這確實是用戶發送的請求。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"php"},"content":[{"type":"text","text":"\n
\n  \n  \n  \">\n  \n
"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"然後在服務器端進行Hash值驗證。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"php"},"content":[{"type":"text","text":""}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這個方法個人覺得已經"},{"type":"text","marks":[{"type":"strong"}],"text":"可以杜絕99%的CSRF攻擊了"},{"type":"text","text":",那還有1%呢....由於用戶的 Cookie 很容易由於網站的 XSS 漏洞而被盜取,這就另外的1%。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"一般的攻擊者看到有需要算Hash值,基本都會放棄了,某些除外,所以如果需要100%的杜絕,這個不是最好的方法。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"3.2 驗證碼"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"思路是:每次用戶提交都需要用戶在表單中填寫一個圖片上的隨機字符串,這個方案可以完全解決CSRF,但易用性差,並且驗證碼圖片的使用涉及 MHTML 的Bug,可能在某些版本的微軟IE中受影響。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"3.3 One-Time Tokens(不同的表單包含一個不同的僞隨機值)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"需要注意“"},{"type":"text","marks":[{"type":"strong"}],"text":"並行會話的兼容"},{"type":"text","text":"”。如果用戶在一個站點上同時打開了兩個不同的表單,CSRF保護措施不應該影響到他對任何表單的提交。考慮一下如果每次表單被裝入時站點生成一個僞隨機值來覆蓋以前的僞隨機值將會發生什麼情況:用戶只能成功地提交他最後打開的表單,因爲所有其他的表單都含有非法的僞隨機值。必須小心操作以確保CSRF保護措施不會影響選項卡式的瀏覽或者利用多個瀏覽器窗口瀏覽一個站點。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"php 實現如下:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"1","normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"先是 "},{"type":"codeinline","content":[{"type":"text","text":"Token"}]},{"type":"text","text":" 令牌生成函數("},{"type":"codeinline","content":[{"type":"text","text":"gen_token()"}]},{"type":"text","text":")和 "},{"type":"codeinline","content":[{"type":"text","text":"Session"}]},{"type":"text","text":" 令牌生成函數("},{"type":"codeinline","content":[{"type":"text","text":"gen_stoken()"}]},{"type":"text","text":"):"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"php"},"content":[{"type":"text","text":""}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"2","normalizeStart":"2"},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"WEB表單生成隱藏輸入域的函數: "}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"php"},"content":[{"type":"text","text":" \";\n  }\n?>"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"3","normalizeStart":"3"},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"WEB表單結構:"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"php"},"content":[{"type":"text","text":"\n
\n \n \n gen_input(); ?>\n \n
"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"4","normalizeStart":"4"},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"text","text":"服務端覈對令牌"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這一步很簡單,不做詳細介紹。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"四、XSS"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"注意"},{"type":"text","text":": 本文簡單介紹 XSS 知識,具體詳細可以閱讀 "},{"type":"text","marks":[{"type":"strong"}],"text":"FEWY"},{"type":"text","text":" 寫的 "},{"type":"link","attrs":{"href":"https://segmentfault.com/a/1190000020402185","title":""},"content":[{"type":"text","text":"《跨站腳本攻擊—XSS》"}]},{"type":"text","text":"https://segmentfault.com/a/1190000020402185。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"1. 概念"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"跨站腳本(英語:Cross-site scripting,通常簡稱爲:XSS)是一種網站應用程序的安全漏洞攻擊,是代碼注入的一種。它允許惡意用戶將代碼注入到網頁上,其他用戶在觀看網頁時就會受到影響。這類攻擊通常包含了HTML以及用戶端腳本語言。"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"—— "},{"type":"link","attrs":{"href":"https://zh.wikipedia.org/wiki/%E8%B7%A8%E7%B6%B2%E7%AB%99%E6%8C%87%E4%BB%A4%E7%A2%BC","title":""},"content":[{"type":"text","text":"維基百科"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"XSS 攻擊,一般是指攻擊者通過在網頁中注入惡意腳本,當用戶瀏覽網頁時,惡意腳本執行,控制用戶瀏覽器行爲的一種攻擊方式。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"常見 XSS 危害有:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"竊取用戶Cookie,獲取用戶隱私,盜取用戶賬號。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"劫持用戶(瀏覽器)會話,從而執行任意操作,例如進行非法轉賬、強制發表日誌、發送電子郵件等。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"強制彈出廣告頁面,刷流量,傳播跨站腳本蠕蟲,網頁掛馬等。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"結合其他漏洞,如 CSRF 漏洞,實施進一步的攻擊。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"2. XSS 分類"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/1d/1d1000c8107b6492354868a774849a22.png","alt":"XSS 分類","title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"3. XSS 防禦"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"3.1 方法1:瀏覽器自帶防禦 (X-XSS-Protection )"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"現今主流瀏覽器(Internet Explorer,Chrome 和 Safari)帶有 HTTP "},{"type":"codeinline","content":[{"type":"text","text":"X-XSS-Protection"}]},{"type":"text","text":" 響應頭,當檢測到跨站腳本攻擊(XSS)時,瀏覽器將停止加載頁面。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"X-XSS-Protection"}]},{"type":"text","text":" 響應頭有以下 4 個值:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"X-XSS-Protection: 0"}]}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"禁止XSS過濾。 "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"X-XSS-Protection: 1"}]}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"啓用XSS過濾(通常瀏覽器是默認的)。 如果檢測到跨站腳本攻擊,瀏覽器將清除頁面(刪除不安全的部分)。 "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"X-XSS-Protection: 1; mode=block"}]}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"啓用XSS過濾。 如果檢測到攻擊,瀏覽器將不會清除頁面,而是阻止頁面加載。 "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"X-XSS-Protection: 1; report="}]}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"啓用XSS過濾。 如果檢測到跨站腳本攻擊,瀏覽器將清除頁面並使用CSP report-uri指令的功能發送違規報告。 "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"注意:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這並不能完全防止反射型 XSS,而且也並不是所有瀏覽器都支持 "},{"type":"codeinline","content":[{"type":"text","text":"X-XSS-Protection"}]},{"type":"text","text":",存在兼容性問題。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"它只對反射型 XSS 有一定的防禦力,其原理也只是檢查 URL 和 DOM 中元素的相關性。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"3.2 方法2:轉義"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"即將常用特殊字符進行轉義,避免攻擊者使用構造特殊字符來注入腳本。需要在客戶端和服務端,都對用戶輸入的數據進行轉義。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"常見需要轉義的特殊字符如 "},{"type":"codeinline","content":[{"type":"text","text":""}]},{"type":"text","text":","},{"type":"codeinline","content":[{"type":"text","text":"&"}]},{"type":"text","text":","},{"type":"codeinline","content":[{"type":"text","text":"\""}]},{"type":"text","text":","},{"type":"codeinline","content":[{"type":"text","text":"'"}]},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"轉義方法:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"js"},"content":[{"type":"text","text":"function escapeHTML(str) {\n if (!str) return '';\n str = str.replace(/&/g, \"&\");\n str = str..replace(//g, \">\");\n str = str..replace(/\"/g, \""\");\n str = str..replace(/'/g, \"'\");\n return str;\n};"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"3.3 方法3:過濾"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"常見於富文本內容,因爲其需要保留 HTML,所以不能直接使用轉義方法,而可以通過使用白名單,來允許特定的 HTML 標籤及屬性,來抵禦 XSS 攻擊。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"3.4 方法4:內容安全策略(CSP)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"http://www.ruanyifeng.com/blog/2016/09/csp.html","title":""},"content":[{"type":"text","text":"內容安全策略(Content Security Policy,CSP)"}]},{"type":"text","text":",實質就是白名單制度,開發者明確告訴客戶端,哪些外部資源可以加載和執行,大大增強了網頁的安全性。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"兩種方法可以啓用 CSP。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"1","normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"通過 HTTP 頭信息的 "},{"type":"codeinline","content":[{"type":"text","text":"Content-Security-Policy"}]},{"type":"text","text":" 的字段:"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"http"},"content":[{"type":"text","text":"Content-Security-Policy: script-src 'self'; \n object-src 'none';\n style-src cdn.example.org third-party.org; \n child-src https:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"2","normalizeStart":"2"},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"通過網頁的 "},{"type":"codeinline","content":[{"type":"text","text":""}]},{"type":"text","text":" 標籤"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"html"},"content":[{"type":"text","text":""}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"上面代碼中,CSP 做了如下配置:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"腳本: 只信任當前域名"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":""}]},{"type":"text","text":"標籤: 不信任任何 URL,即不加載任何資源"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"樣式表: 只信任 "},{"type":"codeinline","content":[{"type":"text","text":"cdn.example.org "}]},{"type":"text","text":"和"},{"type":"codeinline","content":[{"type":"text","text":" third-party.org"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"頁面子內容,如 "},{"type":"codeinline","content":[{"type":"text","text":""}]},{"type":"text","text":"、"},{"type":"codeinline","content":[{"type":"text","text":"
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章