1. GET和POST
- GET
獲取資源
當(dāng)前網(wǎng)絡(luò)請(qǐng)求中,絕大部分使用的是 GET 方法。
- POST
傳輸實(shí)體主體
POST 主要用來傳輸數(shù)據(jù)鳄厌,而 GET 主要用來獲取資源。
- 區(qū)別
- GET 和 POST 的請(qǐng)求都能使用額外的參數(shù)妈踊,但是 GET 的參數(shù)是以查詢字符串出現(xiàn)在 URL 中了嚎,而 POST 的參數(shù)存儲(chǔ)在實(shí)體主體中。不能因?yàn)?POST 參數(shù)存儲(chǔ)在實(shí)體主體中就認(rèn)為它的安全性更高廊营,因?yàn)檎諛涌梢酝ㄟ^一些抓包工具(Fiddler)查看歪泳。
因?yàn)?URL 只支持 ASCII 碼,因此 GET 的參數(shù)中如果存在中文等字符就需要先進(jìn)行編碼露筒。例如中文
會(huì)轉(zhuǎn)換為%E4%B8%AD%E6%96%87
呐伞,而空格會(huì)轉(zhuǎn)換為%20
。POST 參數(shù)支持標(biāo)準(zhǔn)字符集慎式。
GET /test/demo_form.asp?name1=value1&name2=value2 HTTP/1.1
POST /test/demo_form.asp HTTP/1.1
Host: w3schools.com
name1=value1&name2=value2
- GET 方法是安全的伶氢,而 POST 卻不是,因?yàn)?POST 的目的是傳送實(shí)體主體內(nèi)容瘪吏,這個(gè)內(nèi)容可能是用戶上傳的表單數(shù)據(jù)癣防,上傳成功之后,服務(wù)器可能把這個(gè)數(shù)據(jù)存儲(chǔ)到數(shù)據(jù)庫中肪虎,因此狀態(tài)也就發(fā)生了改變劣砍。
2. Cookies
- 用途
- 會(huì)話狀態(tài)管理(如用戶登錄狀態(tài)、購物車扇救、游戲分?jǐn)?shù)或其它需要記錄的信息)
- 個(gè)性化設(shè)置(如用戶自定義設(shè)置刑枝、主題等)
- 瀏覽器行為跟蹤(如跟蹤分析用戶行為等)
- 創(chuàng)建過程
服務(wù)器發(fā)送的響應(yīng)報(bào)文包含 Set-Cookie 首部字段,客戶端得到響應(yīng)報(bào)文后把 Cookie 內(nèi)容保存到瀏覽器中迅腔。
HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: yummy_cookie=choco
Set-Cookie: tasty_cookie=strawberry
[page content]
客戶端之后對(duì)同一個(gè)服務(wù)器發(fā)送請(qǐng)求時(shí)装畅,會(huì)從瀏覽器中取出 Cookie 信息并通過 Cookie 請(qǐng)求首部字段發(fā)送給服務(wù)器。
GET /sample_page.html HTTP/1.1
Host: www.example.org
Cookie: yummy_cookie=choco; tasty_cookie=strawberry
- 分類
會(huì)話期 Cookie:瀏覽器關(guān)閉之后它會(huì)被自動(dòng)刪除沧烈,也就是說它僅在會(huì)話期內(nèi)有效掠兄。
持久性 Cookie:指定過期時(shí)間(Expires)或有效期(max-age)之后就成為了持久性的 Cookie
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;
- 作用域
Domain 標(biāo)識(shí)指定了哪些主機(jī)可以接受 Cookie。如果不指定,默認(rèn)為當(dāng)前文檔的主機(jī)(不包含子域名)蚂夕。如果指定了 Domain迅诬,則一般包含子域名。例如婿牍,如果設(shè)置 Domain=mozilla.org侈贷,則 Cookie 也包含在子域名中(如 developer.mozilla.org)。
Path 標(biāo)識(shí)指定了主機(jī)下的哪些路徑可以接受 Cookie(該 URL 路徑必須存在于請(qǐng)求 URL 中)等脂。以字符 %x2F ("/") 作為路徑分隔符俏蛮,子路徑也會(huì)被匹配。例如上遥,設(shè)置 Path=/docs搏屑,則以下地址都會(huì)匹配:
/docs
/docs/Web/
/docs/Web/HTTP
- JavaScript
瀏覽器通過 document.cookie 屬性可創(chuàng)建新的 Cookie,也可通過該屬性訪問非 HttpOnly 標(biāo)記的 Cookie粉楚。
document.cookie = "yummy_cookie=choco";
document.cookie = "tasty_cookie=strawberry";
console.log(document.cookie);
- HttpOnly
標(biāo)記為 HttpOnly 的 Cookie 不能被 JavaScript 腳本調(diào)用辣恋。跨站腳本攻擊 (XSS) 常常使用 JavaScript 的 document.cookie API 竊取用戶的 Cookie 信息解幼,因此使用 HttpOnly 標(biāo)記可以在一定程度上避免 XSS 攻擊抑党。
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly
- Secure
標(biāo)記為 Secure 的 Cookie 只能通過被 HTTPS 協(xié)議加密過的請(qǐng)求發(fā)送給服務(wù)端包警。但即便設(shè)置了 Secure 標(biāo)記撵摆,敏感信息也不應(yīng)該通過 Cookie 傳輸,因?yàn)?Cookie 有其固有的不安全性害晦,Secure 標(biāo)記也無法提供確實(shí)的安全保障特铝。 - Session
除了可以將用戶信息通過 Cookie 存儲(chǔ)在用戶瀏覽器中,也可以利用 Session 存儲(chǔ)在服務(wù)器端壹瘟,存儲(chǔ)在服務(wù)器端的信息更加安全鲫剿。
Session 可以存儲(chǔ)在服務(wù)器上的文件、數(shù)據(jù)庫或者內(nèi)存中稻轨。也可以將 Session 存儲(chǔ)在 Redis 這種內(nèi)存型數(shù)據(jù)庫中灵莲,效率會(huì)更高。
使用 Session 維護(hù)用戶登錄狀態(tài)的過程如下:
- 用戶進(jìn)行登錄時(shí)殴俱,用戶提交包含用戶名和密碼的表單政冻,放入 HTTP 請(qǐng)求報(bào)文中;
- 服務(wù)器驗(yàn)證該用戶名和密碼线欲,如果正確則把用戶信息存儲(chǔ)到 Redis 中明场,它在 Redis 中的 Key 稱為 Session ID;
- 服務(wù)器返回的響應(yīng)報(bào)文的 Set-Cookie 首部字段包含了這個(gè) Session ID李丰,客戶端收到響應(yīng)報(bào)文之后將該 Cookie 值存入瀏覽器中苦锨;
- 客戶端之后對(duì)同一個(gè)服務(wù)器進(jìn)行請(qǐng)求時(shí)會(huì)包含該 Cookie 值,服務(wù)器收到之后提取出 Session ID,從 Redis 中取出用戶信息舟舒,繼續(xù)之前的業(yè)務(wù)操作拉庶。
應(yīng)該注意 Session ID 的安全性問題,不能讓它被惡意攻擊者輕易獲取秃励,那么就不能產(chǎn)生一個(gè)容易被猜到的 Session ID 值砍的。此外,還需要經(jīng)常重新生成 Session ID莺治。在對(duì)安全性要求極高的場(chǎng)景下廓鞠,例如轉(zhuǎn)賬等操作,除了使用 Session 管理用戶狀態(tài)之外谣旁,還需要對(duì)用戶進(jìn)行重新驗(yàn)證床佳,比如重新輸入密碼,或者使用短信驗(yàn)證碼等方式榄审。
- 瀏覽器禁用Cookie
此時(shí)無法使用 Cookie 來保存用戶信息砌们,只能使用 Session。除此之外搁进,不能再將 Session ID 存放到 Cookie 中浪感,而是使用 URL 重寫技術(shù),將 Session ID 作為 URL 的參數(shù)進(jìn)行傳遞饼问。 - Cookie與Session的選擇
- Cookie 只能存儲(chǔ) ASCII 碼字符串影兽,而 Session 則可以存儲(chǔ)任何類型的數(shù)據(jù),因此在考慮數(shù)據(jù)復(fù)雜性時(shí)首選 Session莱革;
- Cookie 存儲(chǔ)在瀏覽器中峻堰,容易被惡意查看。如果非要將一些隱私數(shù)據(jù)存在 Cookie 中盅视,可以將 Cookie 值進(jìn)行加密捐名,然后在服務(wù)器進(jìn)行解密;
- 對(duì)于大型網(wǎng)站闹击,如果用戶所有的信息都存儲(chǔ)在 Session 中镶蹋,那么開銷是非常大的,因此不建議將所有的用戶信息都存儲(chǔ)到 Session 中赏半。
3. 緩存--Expires 和 max-age 的區(qū)別
Expires和max-age都可以用來指定文檔的過期時(shí)間贺归,但是二者有一些細(xì)微差別。
- Expires在HTTP/1.0中已經(jīng)定義除破,Cache-Control:max-age在HTTP/1.1中才有定義牧氮,為了向下兼容,僅使用max-age不夠瑰枫;
- Expires指定一個(gè)絕對(duì)的過期時(shí)間(GMT格式),這么做會(huì)導(dǎo)致至少2個(gè)問題1)客戶端和服務(wù)器時(shí)間不同步導(dǎo)致Expires的配置出現(xiàn)問題 2)很容易在配置后忘記具體的過期時(shí)間踱葛,導(dǎo)致過期來臨出現(xiàn)浪涌現(xiàn)象丹莲;
- max-age 指定的是從文檔被訪問后的存活時(shí)間,這個(gè)時(shí)間是個(gè)相對(duì)值(比如:3600s),相對(duì)的是文檔第一次被請(qǐng)求時(shí)服務(wù)器記錄的Request_time(請(qǐng)求時(shí)間)
- Expires指定的時(shí)間可以是相對(duì)文件的最后訪問時(shí)間(Atime)或者修改時(shí)間(MTime),而max-age相對(duì)對(duì)的是文檔的請(qǐng)求時(shí)間(Atime)
- 在Apache中尸诽,max-age是根據(jù)Expires的時(shí)間來計(jì)算出來的max-age = expires- request_time:(mod_expires.c)
如果響應(yīng)包括Expires頭和max-age指令甥材, 則max-age指令會(huì)覆蓋Expires頭。
4. 連接管理
短連接:如果每進(jìn)行一次 HTTP 通信就要新建一個(gè) TCP 連接性含。
當(dāng)瀏覽器訪問一個(gè)包含多張圖片的 HTML 頁面時(shí)洲赵,除了請(qǐng)求訪問的 HTML 頁面資源,還會(huì)請(qǐng)求圖片資源商蕴。如果每進(jìn)行一次 HTTP 通信就要新建一個(gè) TCP 連接叠萍,那么開銷會(huì)很大。
長(zhǎng)連接:只需要建立一次 TCP 連接就能進(jìn)行多次 HTTP 通信绪商。
- 從 HTTP/1.1 開始默認(rèn)是長(zhǎng)連接的苛谷,如果要斷開連接,需要由客戶端或者服務(wù)器端提出斷開格郁,使用
Connection : close
腹殿; - 在 HTTP/1.1 之前默認(rèn)是短連接的,如果需要使用長(zhǎng)連接例书,則使用
Connection : Keep-Alive
锣尉。
流水線:在同一條長(zhǎng)連接上連續(xù)發(fā)出請(qǐng)求,而不用等待響應(yīng)返回决采,這樣可以減少延遲自沧。
5. HTTPS
HTTP 有以下安全性問題:
- 使用明文進(jìn)行通信,內(nèi)容可能會(huì)被竊聽织狐;
- 不驗(yàn)證通信方的身份暂幼,通信方的身份有可能遭遇偽裝筏勒;
- 無法證明報(bào)文的完整性移迫,報(bào)文有可能遭篡改。
HTTPS 并不是新協(xié)議管行,而是讓 HTTP 先和 SSL(Secure Sockets Layer)通信厨埋,再由 SSL 和 TCP 通信,也就是說 HTTPS 使用了隧道進(jìn)行通信捐顷。
通過使用 SSL荡陷,HTTPS 具有了加密(防竊聽)、認(rèn)證(防偽裝)和完整性保護(hù)(防篡改)迅涮。
加密方式:HTTPS 采用混合的加密機(jī)制废赞,使用非對(duì)稱密鑰加密用于傳輸對(duì)稱密鑰來保證傳輸過程的安全性,之后使用對(duì)稱密鑰加密進(jìn)行通信來保證通信過程的效率叮姑。
HTTP/1.1 的首部帶有大量信息唉地,而且每次都要重復(fù)發(fā)送据悔。
HTTP/2.0 要求客戶端和服務(wù)器同時(shí)維護(hù)和更新一個(gè)包含之前見過的首部字段表,從而避免了重復(fù)傳輸耘沼。