IOS 使用自簽名證書開發HTTPS文件傳輸

@[TOC](IOS 使用自簽名證書開發HTTPS文件傳輸)

1. HTTPS文件傳輸簡介

最近由于項目需要實現IOS數據通過https實現與機器人端的文件傳輸功能。參考了很多資料,最終實現了一個文件傳輸功能,其中在https證書配置方面遇到了很多坑,寫這篇文章一是對這段工作的總結,方便自己以后查閱,同時也希望幫助到更多有同樣需求的哥們,少走一點彎路,節省時間。

2. HTTPS 對比HTTP簡介

2.1 HTTP的一些基本概念

  • 什么是HTTP

HTTP:是互聯網上應用最為廣泛的一種網絡協議,是一個客戶端和服務器端請求和應答的標準(TCP),用于從WWW服務器傳輸超文本到本地瀏覽器的傳輸協議,它可以使瀏覽器更加高效,使網絡傳輸減少。
HTTP有稱為:超文本傳輸協議(HTTP,HyperText Transfer Protocol)所有的WWW文件都必須遵守這個標準。設計HTTP最初的目的是為了提供一種發布和接收HTML頁面的方法。1960年美國人Ted Nelson構思了一種通過計算機處理文本信息的方法,并稱之為超文本(hypertext),這成為了HTTP超文本傳輸協議標準架構的發展根基。Ted Nelson組織協調萬維網協會(World Wide Web Consortium)和互聯網工程工作小組(Internet Engineering Task Force )共同合作研究,最終發布了一系列的RFC,其中著名的RFC 2616定義了HTTP 1.1。

  • HTTP有什么作用?

主要功能:

  1. HTTP協議(HyperText Transfer Protocol,超文本傳輸協議)是用于從WWW服務器傳輸超文本到本地瀏覽器的傳輸協議。它可以使瀏覽器更加高效,使網絡傳輸減少。它不僅保證計算機正確快速地傳輸超文本文檔,還確定傳輸文檔中的哪一部分,以及哪部分內容首先顯示(如文本先于圖形)等。
  2. HTTP是客戶端瀏覽器或其他程序與Web服務器之間的應用層通信協議。在Internet上的Web服務器上存放的都是超文本信息,客戶機需要通過HTTP協議傳輸所要訪問的超文本信息。HTTP包含命令和傳輸信息,不僅可用于Web訪問,也可以用于其他因特網/內聯網應用系統之間的通信,從而實現各類應用資源超媒體訪問的集成。
  3. 我們在瀏覽器的地址欄里輸入的網站地址叫做URL (Uniform Resource Locator,統一資源定位符)。就像每家每戶都有一個門牌地址一樣,每個網頁也都有一個Internet地址。當你在瀏覽器的地址框中輸入一個URL或是單擊一個超級鏈接時,URL就確定了要瀏覽的地址。瀏覽器通過超文本傳輸協議(HTTP),將Web服務器上站點的網頁代碼提取出來,并翻譯成漂亮的網頁。

HTTP是一個客戶端和服務器端請求和應答的標準(TCP)??蛻舳耸墙K端用戶,服務器端是網站。通過使用Web瀏覽器、網絡爬蟲或者其它的工具,客戶端發起一個到服務器上指定端口(默認端口為80)的HTTP請求。(我們稱這個客戶端)叫用戶代理(user agent)。應答的服務器上存儲著(一些)資源,比如HTML文件和圖像。(我們稱)這個應答服務器為源服務器(origin server)。在用戶代理和源服務器中間可能存在多個中間層,比如代理,網關,或者隧道(tunnels)。盡管TCP/IP協議是互聯網上最流行的應用,HTTP協議并沒有規定必須使用它和(基于)它支持的層。 事實上,HTTP可以在任何其他互聯網協議上,或者在其他網絡上實現。HTTP只假定(其下層協議提供)可靠的傳輸,任何能夠提供這種保證的協議都可以被其使用。
通常,由HTTP客戶端發起一個請求,建立一個到服務器指定端口(默認是80端口)的TCP連接。HTTP服務器則在那個端口監聽客戶端發送過來的請求。一旦收到請求,服務器(向客戶端)發回一個狀態行,比如"HTTP/1.1 200 OK",和(響應的)消息,消息的消息體可能是請求的文件、錯誤消息、或者其它一些信息。HTTP使用TCP而不是UDP的原因在于(打開)一個網頁必須傳送很多數據,而TCP協議提供傳輸控制,按順序組織數據,和錯誤糾正。
通過HTTP或者HTTPS協議請求的資源由統一資源標示符(Uniform Resource Identifiers)(或者,更準確一些,URLs)來標識。

  • HTTP 的主要特點?
  1. 基于請求/響應模型的協議。請求和響應必須成對,先有請求后有響應
  2. http協議默認端口:80
  3. 簡單快速:客戶向服務器請求服務時,只需傳送請求方法和路徑。請求方法常用的有GET、HEAD、POST。每種方法規定了客戶與服務器聯系的類型不同。由于HTTP協議簡單,使得HTTP服務器的程序規模小,因而通信速度很快。
  4. 靈活:HTTP允許傳輸任意類型的數據對象。正在傳輸的類型由Content-Type加以標記。
    5 .無連接:無連接的含義是限制每次連接只處理一個請求。服務器處理完客戶的請求,并收到客戶的應答后,即斷開連接。采用這種方式可以節省傳輸時間。
  5. 無狀態:HTTP協議是無狀態協議。無狀態是指協議對于事務處理沒有記憶能力。缺少狀態意味著如果后續處理需要前面的信息,則它必須重傳,這樣可能導致每次連接傳送的數據量增大。另一方面,在服務器不需要先前信息時它的應答就較快。
  • HTTP協議有哪些主要版本?
版本 產生時間 內容 發展現狀
HTTP/0.9 1991年 不涉及數據包傳輸,規定客戶端和服務器之間通信格式,只能GET請求 沒有作為正式的標準
HTTP/1.0 1996年 傳輸內容格式不限制,增加PUT、PATCH、HEAD、 OPTIONS、DELETE命令 正式作為標準
HTTP/1.1 1997年 持久連接(長連接)、節約帶寬、HOST域、管道機制、分塊傳輸編碼 2015年前使用最廣泛
HTTP/2 2015年 多路復用、服務器推送、頭信息壓縮、二進制協議等 逐漸覆蓋市場

HTTP/0.9 :只接受GET一種請求方法,沒有在通信中指定版本號,且不支持請求頭。由于該版本不支持POST方法,因此客戶端無法向服務器傳遞太多信息。
HTTP/1.0 :第一個在通信中指定的版本號,至今被廣泛采用,特別是在代理服務器中。
HTTP/1.1 :當前版本號,持久連接被默認采用,并能很好地配合代理服務器工作。還支持以管道方式在同時發送多個請求,以便降低線路負載,提高傳輸速度。
HTTP/2.0 正在開發中······

  • HTTP/1.1與HTTP/1.0的區別?

主要區別:
在同一個tcp的連接中可以傳送多個HTTP請求和響應.
多個請求和響應可以重疊,多個請求和響應可以同時進行.
更加多的請求頭和響應頭(比如HTTP1.0沒有host的字段).
總之在HTTP/1.0中,大多實現為每個請求/響應交換使用新的連接。在HTTP/1.1中,一個連接可用于一次或多次請求/響應交換,盡管連接可能由于各種原因被關閉。

  1. persistent connection(持久連接)
    HTTP/1.0中,每對請求/ 響應都使用一個新的連接。
    HTTP/1.1則支持持久連接(默認)。
  2. Host域
    HTTP/1.1在請求消息頭多一個Host域;HTTP/1.0 則沒有這個域,建立TCP連接的時候已經指定了IP地址,而且默認一個IP地址只對應一個主機名,IP地址上只有一個host。
  3. 帶寬優化
    HTTP/1.1中在請求消息中引入了range頭域,它允許只請求資源的某個部分。在響應消息中Content-Range頭域聲明了返回的這部分對象 的偏移值和長度。如果服務器相應地返回了對象所請求范圍的內容,則響應碼為206(Partial Content),它可以防止Cache將響應誤以為是完整的一個對象。請求消息中如果包含比較大的實體內容,但不確定服務器是否能夠接收該請求(如是否有權限),此時若貿然發出帶實體的請求,如果被拒絕也會浪費帶寬。 HTTP/1.1加入了一個新的狀態碼100(Continue)??蛻舳耸孪劝l送一個只帶頭域的請求,如果服務器因為權限拒絕了請求,就回送響應碼 401(Unauthorized);如果服務器接收此請求就回送響應碼100,客戶端就可以繼續發送帶實體的完整請求了。注意,HTTP/1.0的客戶 端不支持100響應碼。
    節省帶寬資源的一個非常有效的做法就是壓縮要傳送的數據。Content-Encoding是對消息進行端到端(end-to-end)的編碼,它可能是 資源在服務器上保存的固有格式(如jpeg圖片格式);在請求消息中加入Accept-Encoding頭域,它可以告訴服務器客戶端能夠解碼的編碼方 式。而Transfer-Encoding是逐段式(hop-by-hop)的編碼,如Chunked編碼。在請求消息中加入TE頭 域用來告訴服務器能夠接收的transfer-coding方式。
  4. 請求方法和狀態碼
    HTTP1.1增加了OPTIONS, PUT, DELETE, TRACE, CONNECT這些Request方法
    HTTP/1.0中只定義了16個狀態響應碼,對錯誤或警告的提示不夠具體。HTTP/1.1引入了一個Warning頭域,增加對錯誤或警告信息的描述。
    在HTTP/1.1中新增了24個狀態響應碼,如409(Conflict)表示請求的資源與資源的當前狀態發生沖突;410(Gone)表示服務器上的某個資源被永久性的刪除。
  5. 內容協商
    為 了滿足互聯網使用不同母語和字符集的用戶,一些網絡資源有不同的語言版本(如中文版、英文版)。HTTP/1.0定義了內容協商 (content negotiation)的概念,也就是說客戶端可以告訴服務器自己可以接收以何種語言(或字符集)表示的資源。例如如果服務器不能明確 客戶端需要何種類型的資源,會返回300(Multiple Choices),并包含一個列表,用來聲明該資源的不同可用版本,然后客戶端在請求消息中包含Accept-Language和Accept- Charset頭域指定需要的版本。
  6. 狀態碼
    100~199:信息狀態碼,表示成功接收請求,要求客戶端繼續提交下一次請求才能完成整個處理過程
    100(continue)繼續發送
    200~299:成功狀態碼,表示成功接收請求并已完成整個處理過程,常用200(OK)成功接收
    300~399:重定向狀態碼,例如,請求的資源已經移動一個新地址,常用302、307和304
    400~499:客戶端的請求有錯誤,常用404(Not Found),403(Fobidden)
    500~599:服務器端出現錯誤,常用 500
  • HTTP1.1 解決了HTTP1.0的相關痛點?
  1. 一個WEB站點每天可能要接收到上百萬的用戶請求,為了提高系統的效率,HTTP 1.0規定瀏覽器與服務器只保持短暫的連接,瀏覽器的每次請求都需要與服務器建立一個TCP連接,服務器完成請求處理后立即斷開TCP連接,服務器不跟蹤每個客戶也不記錄過去的請求。
  2. 這也造成了一些性能上的缺陷,例如,一個包含有許多圖像的網頁文件中并沒有包含真正的圖像數據內容,而只是指明了這些圖像的URL地址,當WEB瀏覽器訪問這個網頁文件時,瀏覽器首先要發出針對該網頁文件的請求,當瀏覽器解析WEB服務器返回的該網頁文檔中的HTML內容時,發現其中的img圖像標簽后,瀏覽器將根據img標簽中的src屬性所指定的URL地址再次向服務器發出下載圖像數據的請求。
  3. 顯然,訪問一個包含有許多圖像的網頁文件的整個過程包含了多次請求和響應,每次請求和響應都需要建立一個單獨的連接,每次連接只是傳輸一個文檔和圖像,上一次和下一次請求完全分離。即使圖像文件都很小,但是客戶端和服務器端每次建立和關閉連接卻是一個相對比較費時的過程,并且會嚴重影響客戶機和服務器的性能。當一個網頁文件中包含Applet,JavaScript文件,CSS文件等內容時,也會出現類似上述的情況。
  4. 為了克服HTTP 1.0的這個缺陷,HTTP 1.1支持持久連接,在一個TCP連接上可以傳送多個HTTP請求和響應,減少了建立和關閉連接的消耗和延遲。一個包含有許多圖像的網頁文件的多個請求和應答可以在一個連接中傳輸,但每個單獨的網頁文件的請求和應答仍然需要使用各自的連接。HTTP 1.1還允許客戶端不用等待上一次請求結果返回,就可以發出下一次請求,但服務器端必須按照接收到客戶端請求的先后順序依次回送響應結果,以保證客戶端能夠區分出每次請求的響應內容,這樣也顯著地減少了整個下載過程所需要的時間。基于HTTP 1.1協議的客戶機與服務器的信息交換過程。
  5. 可見HTTP 1.1在繼承了HTTP 1.0優點的基礎上,也克服了HTTP 1.0的性能問題。不僅如此,HTTP 1.1還通過增加更多的請求頭和響應頭來改進和擴充HTTP 1.0的功能。例如,由于HTTP 1.0不支持Host請求頭字段,WEB瀏覽器無法使用主機頭名來明確表示要訪問服務器上的哪個WEB站點,這樣就無法使用WEB服務器在同一個IP地址和端口號上配置多個虛擬WEB站點。在HTTP 1.1中增加Host請求頭字段后,WEB瀏覽器可以使用主機頭名來明確表示要訪問服務器上的哪個WEB站點,這才實現了在一臺WEB服務器上可以在同一個IP地址和端口號上使用不同的主機名來創建多個虛擬WEB站點。HTTP 1.1的持續連接,也需要增加新的請求頭來幫助實現,例如,Connection請求頭的值為Keep-Alive時,客戶端通知服務器返回本次請求結果后保持連接;Connection請求頭的值為close時,客戶端通知服務器返回本次請求結果后關閉連接。HTTP 1.1還提供了與身份認證、狀態管理和Cache緩存等機制相關的請求頭和響應頭。
  • HTTP報文格式
HTTP報文格式
  • HTTP請求報文
  1. HTTP請求報文組成:請求行+請求頭+請求體


    HTTP請求報文組成
  2. 請求行(HTTP請求報文的第一行)
    請求行由方法字段、URL字段和HTTP協議版本字段。其中,方法字段嚴格區分大小寫,當前HTTP協議中的方法都是大寫,方法字段如下介紹如下:
  3. 方法字段
    ①GET:請求獲取Request-URI(URI:通用資源標識符,URL是其子集,URI注重的是標識,而URL強調的是位置,可以將URL看成原始的URI),所標識的資源
    ②POST:在Request-URI所標識的資源后附加新的數據;支持HTML表單提交,表單中有用戶添入的數據,這些數據會發送到服務器端,由服務器存儲至某位置(例如發送處理程序)
    ③HEAD:請求Request-URI所標識的資源響應消息報頭,HEAD方法可以在響應時不返回消息體。
    ④PUT:與GET相反,請求服務器存儲一個資源,并用Request-URI做為其標識;例如發布系統。
    ⑤DELETE:請求刪除URL指向的資源
    ⑥OPTIONS:請求查詢服務器的性能,或者查詢與資源相關的選項
    ⑦TRACE:跟蹤請求要經過的防火墻、代理或網關等,主要用于測試或診斷
    ⑧CONNECT保留將來使用
  4. URL
    一個完整的包括類型、主機名和可選路徑名的統一資源引用名,如:http://www.example.com/path/to/file.html
  5. 請求頭部:位于請求行的下面
    請求報文中常見的標頭有:
    Connetion標頭(連接管理)、Host標頭(指定請求資源的主機)、Range標頭(請求實體的字節范圍)、User-Agent標頭(包含發出請求的用戶信息)、Accept標頭(首選的媒體類型)、Accept-Language(首選的自然語言)
  6. HTTP首部:
    6.1 通用首部:請求和響應都可以使用的;
    Connection:定義C/S之間關于請求/響應的有關選項
    對于http/1.0, Connection: keep-alive
    Via: 顯示了報文經過的中間節點
    Cache-Control: 緩存指示
    6.2 實體首部:用于指定實體屬性
    實體主體用于POST方法中。用戶向Web服務器提交表單數據的時候,需要使用POST方法,此時主體中包含用戶添寫在表單的各個屬性字段的值,當Web服務器收到POST方法的HTTP請求報文后,可以從實體中取出需要的屬性字段的值。
    也就是說,當用戶通過Web瀏覽器向Web服務器發送請求時,Web瀏覽器會根據用戶的具體請求來選擇不同的HTTP請求方法,再將相應的URL和HTTP協議版本及相關的標頭填入頭部行中,若是POST方法,還會將相關的表單數據填入實體主體中,產生一個HTTP請求報文,然后將這個報文發送給Web服務器。
  1. 請求報文分析:


    請求報文分析
  2. 常見請求頭屬性:
    Location: 資源的新位置
    Allow: 允許對此資源使用的請求方法
    1、內容首部:
    Content-Encoding:支持的編碼
    Content-Language:支持的自然語言
    Content-Length:文本長度
    Content-Location:資源所在位置
    Content-Range:在整個資源中此實體表示的字節范圍
    Content-Type:主體的對象類型
    2、緩存首部:
    ETag: 實體標簽
    Expires: 過期期限
    Last-Modified: 上一次的修改時間
    請求首部:
    Host: 請求的主機名和端口號,虛擬主機環境下用于不同的虛擬主機
    Referer:指明了請求當前資源的原始資源的URL
    User-Agent: 用戶代理,使用什么工具發出的請求
    1、Accept首部:用戶標明客戶自己更傾向于支持的能力
    Accept: 指明服務器能發送的媒體類型
    Accept-Charset: 支持使用的字符集
    Accept-Encoding: 支持使用的編碼方式
    Accept-Language: 支持使用語言
    2、條件請求首部:
    Expect: 告訴服務器能夠發送來哪些媒體類型
    If-Modified-Since: 是否在指定時間以來修改過此資源
    If-None-Match:如果提供的實體標記與當前文檔的實體標記不符,就獲取此文檔
    跟安全相關的請求首部:
    Authorization: 客戶端提交給服務端的認證數據,如帳號和密碼
    Cookie: 客戶端發送給服務器端身份標識

  3. 請求字段
    1.Accept 作用:瀏覽器客戶端用來告訴服務端能接受什么類型的響應。
    例如: Accept: text/html 代表瀏覽器可以接受服務器回發html文檔,如果服務器無法返回text/html類型的數據,服務器應該返回一個406錯誤(non acceptable)
    通配符 * 代表任意類型。如: Accept: / 代表瀏覽器可以處理所有類型
    2.Accept-Encoding 作用:瀏覽器客戶端用來告訴服務器能接受什么編碼格式,包括字符編碼、壓縮方式等
    例如:Accept-Encoding:gzip, deflate
    3.Accept-Language 作用:瀏覽器客戶端用來告訴服務器能接受什么語言。
    例如:Accept-Language:zh-CN,zh;q=0.9
    4.Connection 作用:客戶端或服務端用來告訴對方當前tcp連接的狀態,默認為keep-alive,即長連接。
    例如:Connection:close 在響應結束后關閉連接
    5.Host 作用:指定要請求的資源所在的主機和端口,通常從url里獲取。這個字段是必需的。
    例如:我們在地址欄輸入:http://www.baidu.com Host:www.baidu.com
    6.Referer 作用:瀏覽器客戶端用來告訴服務器這個請求是從哪個頁面鏈接過來的,即請求來源。
    7.User-Agent 作用:告訴服務器,客戶端使用的操作系統、瀏覽器版本和名稱
    例如:Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36
    另外,有些屬性不一定會有但比較常見:
    1.Cache-Control 作用:客戶端瀏覽器用來判斷是否需要用本地緩存。默認值為private;常用值有private、no-cache、max-age、must-revalidate。具體場景舉例:
    a.打開新窗口時值為private、no-cache、must-revalidate,那么打開新窗口訪問時都會重新訪問服務器。而如果指定了max-age值(單位為秒),那么在此值內的時間里就不會重新訪問服務器,例如:
    Cache-control: max-age=5(表示當訪問此網頁后的5秒內再次訪問不會去服務器)
    b.在地址欄回車
    值為private或must-revalidate則只有第一次訪問時會訪問服務器,以后就不再訪問。
    值為no-cache,那么每次都會訪問。
    值為max-age,則在過期之前不會重復訪問。
    c.按后退按扭
    值為private、must-revalidate、max-age,則不會重訪問,
    值為no-cache,則每次都重復訪問
    d.按刷新按扭
    無論為何值,都會重復訪問
    2.Cookie 作用:客戶端瀏覽器用來存儲一些用戶信息以便讓服務器辨別用戶身份的(大多數需要登錄的網站上面會比較常見),比如用戶名和密碼,sessionId等。
    3.If-Modify-Since 作用:把瀏覽器端緩存頁面的最后修改時間(精確到秒)發送到服務器去,服務器會把這個時間與服務器上實際文件的最后修改時間進行對比。如果時間一致,那么返回304,客戶端就直接使用本地緩存文件。如果時間不一致,就會返回200和新的文件內容以及新的修改時間(Last-Modify)。客戶端接到之后,會丟棄舊文件,把新文件緩存起來,并顯示在瀏覽器中。
    例如:Wed, 30 May 2018 08:32:42 GMT
    4.If-None-Match 作用:If-None-Match和ETag一起工作,工作原理是在HTTP Response中添加ETag信息。 當用戶再次請求該資源時,將在HTTP Request 中加入If-None-Match信息(ETag的值)。如果服務器驗證資源的ETag沒有改變(該資源沒有更新),將返回一個304狀態告訴客戶端使用本地緩存文件。否則將返回200狀態和新的資源和Etag. 使用這樣的機制將提高網站的性能。
    例如: If-None-Match: W/"3119-1437038474000"
    注意:If-Modify-Since和If-None-Match都可以給服務器用來判斷所請求的文件距離上次訪問之間是否被修改過,不過If-Modify-Since只能精確到秒,而If-None-Match只要文件修改過就會變化。
    Etag的使用場景:1.有些文件需要頻繁更新,但是文件內容并沒有變化。
    2.同一文件存儲在多臺web服務器中,用戶請求在多臺之間輪詢。

  • 響應報文
  1. HTTP響應報文同樣也分為三部分,有狀態行、首部行、實體


    響應報文
  2. 狀態行:HTTP響應報文的第一行
    狀態行包括三個字段:協議版本、狀態碼與原因短語。
  3. 狀態碼:
    1xx:
    這一類型的狀態碼,代表請求已被接受,需要繼續處理。這類響應是臨時響應,只包含狀態行和某些可選的響應頭信息,并以空行結束。
    2xx:
    這一類型的狀態碼,代表請求已成功被服務器接收、理解、并接受。
    3xx:
    這類狀態碼代表需要客戶端采取進一步的操作才能完成請求。通常,這些狀態碼用來重定向,后續的請求地址(重定向目標)在本次響應的Location域中指明。
    4xx:
    這類的狀態碼代表客戶端類的錯誤
    5xx:
    服務器類的錯誤
  4. 常見狀態碼:


    常見狀態碼
  5. 響應首部


    響應首部
  6. 響應字段
    響應首部(首部行):位于響應報文狀態行之后
    Date標頭:消息產生的時間
    Age標頭:(從最初創建開始)響應持續時間
    Server標頭: 向客戶端標明服務器程序名稱和版本
    ETage標頭:不透明驗證者
    Location標頭:URL備用的位置
    Content-Length標頭:實體的長度
    Content-Tyep標頭:實體的媒體類型
    協商首部:
    Accept-Ranges: 對當前資源來講,服務器所能夠接受的范圍類型
    Vary: 首部列表,服務器會根據列表中的內容挑選出最適合的版本發送給客戶端
    跟安全相關的響應首部:
    Set-Cookie: 服務器端在某客戶端第一次請求時發給令牌
    WWW-Authentication: 質詢,即要求客戶提供帳號和密碼
  7. 實體:
    位于首部行之后
    實體包含了Web客戶端請求的對象。Content-Length標頭及Content-Type標頭用于計算實體的位置、數據類型和數據長度。當Web服務器接收到Web客戶端的請求報文后,對HTTP請求報文進行解析,并將Web客戶端的請求的對象取出打包,通過HTTP響應報文將數據傳回給Web客戶端,如果出現錯誤則返回包含對應錯誤的錯誤代碼和錯誤原因的HTTP響應報文。

2.2 HTTPS 的一些基本概念

  • 什么是HTTPS

HTTPS實際就是HTTP + SSL,就是在HTTP協議的基礎上增加了SSL安全加密傳輸。
《圖解HTTP》這本書中曾提過HTTPS是身披SSL外殼的HTTP。HTTPS是一種通過計算機網絡進行安全通信的傳輸協議,經由HTTP進行通信,利用SSL/TLS建立全信道,加密數據包。HTTPS使用的主要目的是提供對網站服務器的身份認證,同時保護交換數據的隱私與完整性。

TLS是傳輸層加密協議,前身是SSL協議,由網景公司1995年發布,有時候兩者不區分。

  • HTTPS的特點
  1. 內容加密:采用混合加密技術,中間者無法直接查看明文內容
  2. 驗證身份:通過證書認證客戶端訪問的是自己的服務器
  3. 保護數據完整性:防止傳輸的內容被中間人冒充或者篡改

我們可以對比HTTP抓包分析

  1. HTTP抓包如下:


    HTTP抓包
  2. HTTPS抓包:


    HTTPS抓包

    通過抓包可以看到HTTPS中數據不是明文傳輸。HTTPS主要通過RSA混合加密,使用RSA加密客戶端產生的隨機秘鑰,服務器端得到客戶端的秘鑰,雙方就可以使用這個隨機秘鑰進行對稱加密傳輸。

  3. 混合加密:結合非對稱加密和對稱加密技術??蛻舳耸褂脤ΨQ加密生成密鑰對傳輸數據進行加密,然后使用非對稱加密的公鑰再對秘鑰進行加密,所以網絡上傳輸的數據是被秘鑰加密的密文和用公鑰加密后的秘密秘鑰,因此即使被黑客截取,由于沒有私鑰,無法獲取到加密明文的秘鑰,便無法獲取到明文數據。

  4. 數字摘要:通過單向hash函數對原文進行哈希,將需加密的明文“摘要”成一串固定長度(如128bit)的密文,不同的明文摘要成的密文其結果總是不相同,同樣的明文其摘要必定一致,并且即使知道了摘要也不能反推出明文。

  5. 數字簽名技術:數字簽名建立在公鑰加密體制基礎上,是公鑰加密技術的另一類應用。它把公鑰加密技術和數字摘要結合起來,形成了實用的數字簽名技術。

  6. 通過加密后可以做到:
    收方能夠證實發送方的真實身份;
    發送方事后不能否認所發送過的報文;
    收方或非法者不能偽造、篡改報文

  • HTTPS 加密,解密流程
HTTPS 加密,解密流程
  • HTTPS對比HTTP的區別
  1. https協議需要到CA申請證書,一般免費證書較少,因而需要一定費用。(原來網易官網是http,而網易郵箱是https。)
  2. http是超文本傳輸協議,信息是明文傳輸,https則是具有安全性的ssl加密傳輸協議。
  3. http和https使用的是完全不同的連接方式,用的端口也不一樣,前者是80,后者是443。
  4. http的連接很簡單,是無狀態的。Https協議是由SSL+Http協議構建的可進行加密傳輸、身份認證的網絡協議,比http協議安全。(無狀態的意思是其數據包的發送、傳輸和接收都是相互獨立的。無連接的意思是指通信雙方都不長久的維持對方的任何信息。)
  • HTTPS的優點
  1. 使用Https協議可認證用戶和服務器,確保數據發送到正確的客戶機和服務器。
  2. Https協議是由SSL+Http協議構建的可進行加密傳輸、身份認證的網絡協議,要比http協議安全,可防止數據在傳輸過程中不被竊取、修改,確保數據的完整性。
  3. Https是現行架構下最安全的解決方案,雖然不是絕對安全,但它大幅增加了中間人攻擊的成本。
  • HTTPS的缺點
  1. Https協議握手階段比較費時,會使頁面的加載時間延長近。
  2. Https連接緩存不如Http高效,會增加數據開銷,甚至已有的安全措施也會因此而受到影響;
  3. SSL證書通常需要綁定IP,不能在同一IP上綁定多個域名,IPv4資源不可能支撐這個消耗。
  4. Https協議的加密范圍也比較有限。最關鍵的,SSL證書的信用鏈體系并不安全,特別是在某些國家可以控制CA根證書的情況下,中間人攻擊一樣可行。
  • HTTPS SSL加密建立連接過程

如下圖:


HTTPS SSL加密建立連接過程

過程詳解:

  1. ①客戶端的瀏覽器向服務器發送請求,并傳送客戶端SSL 協議的版本號,加密算法的種類,產生的隨機數,以及其他服務器和客戶端之間通訊所需要的各種信息。
  2. ②服務器向客戶端傳送SSL 協議的版本號,加密算法的種類,隨機數以及其他相關信息,同時服務器還將向客戶端傳送自己的證書。
  3. ③客戶端利用服務器傳過來的信息驗證服務器的合法性,服務器的合法性包括:證書是否過期,發行服務器證書的CA 是否可靠,發行者證書的公鑰能否正確解開服務器證書的“發行者的數字簽名”,服務器證書上的域名是否和服務器的實際域名相匹配。如果合法性驗證沒有通過,通訊將斷開;如果合法性驗證通過,將繼續進行第四步。
  4. ④用戶端隨機產生一個用于通訊的“對稱密碼”,然后用服務器的公鑰(服務器的公鑰從步驟②中的服務器的證書中獲得)對其加密,然后將加密后的“預主密碼”傳給服務器。
  5. ⑤如果服務器要求客戶的身份認證(在握手過程中為可選),用戶可以建立一個隨機數然后對其進行數據簽名,將這個含有簽名的隨機數和客戶自己的證書以及加密過的“預主密碼”一起傳給服務器。
  6. ⑥如果服務器要求客戶的身份認證,服務器必須檢驗客戶證書和簽名隨機數的合法性,具體的合法性驗證過程包括:客戶的證書使用日期是否有效,為客戶提供證書的CA 是否可靠,發行CA 的公鑰能否正確解開客戶證書的發行CA 的數字簽名,檢查客戶的證書是否在證書廢止列表(CRL)中。檢驗如果沒有通過,通訊立刻中斷;如果驗證通過,服務器將用自己的私鑰解開加密的“預主密碼”,然后執行一系列步驟來產生主通訊密碼(客戶端也將通過同樣的方法產生相同的主通訊密碼)。
  7. ⑦服務器和客戶端用相同的主密碼即“通話密碼”,一個對稱密鑰用于SSL 協議的安全數據通訊的加解密通訊。同時在SSL 通訊過程中還要完成數據通訊的完整性,防止數據通訊中的任何變化。
  8. ⑧客戶端向服務器端發出信息,指明后面的數據通訊將使用的步驟. ⑦中的主密碼為對稱密鑰,同時通知服務器客戶端的握手過程結束。
  9. ⑨服務器向客戶端發出信息,指明后面的數據通訊將使用的步驟⑦中的主密碼為對稱密鑰,同時通知客戶端服務器端的握手過程結束。
  10. ⑩SSL 的握手部分結束,SSL 安全通道的數據通訊開始,客戶和服務器開始使用相同的對稱密鑰進行數據通訊,同時進行通訊完整性的檢驗。

2.3 HTTPS 與HTTP的區別

1、https協議需要到ca申請證書,一般免費證書較少,因而需要一定費用。
2、http是超文本傳輸協議,信息是明文傳輸,https則是具有安全性的ssl加密傳輸協議。
3、http和https使用的是完全不同的連接方式,用的端口也不一樣,前者是80,后者是443。
4、http的連接很簡單,是無狀態的;HTTPS協議是由SSL+HTTP協議構建的可進行加密傳輸、身份認證的網絡協議,比http協議安全。

3. HTTPS 通訊中SSL處理流程

3.1 SSL建立連接過程

SSL建立連接過程

連接過程:

  1. client向server發送請求https://baidu.com,然后連接到server的443端口,發送的信息主要是隨機值1和客戶端支持的加密算法。
  2. server接收到信息之后給予client響應握手信息,包括隨機值2和匹配好的協商加密算法,這個加密算法一定是client發送給server加密算法的子集。
  3. 隨即server給client發送第二個響應報文是數字證書。服務端必須要有一套數字證書,可以自己制作,也可以向組織申請。區別就是自己頒發的證書需要客戶端驗證通過,才可以繼續訪問,而使用受信任的公司申請的證書則不會彈出提示頁面,這套證書其實就是一對公鑰和私鑰。傳送證書,這個證書其實就是公鑰,只是包含了很多信息,如證書的頒發機構,過期時間、服務端的公鑰,第三方證書認證機構(CA)的簽名,服務端的域名信息等內容。
  4. 客戶端解析證書,這部分工作是由客戶端的TLS來完成的,首先會驗證公鑰是否有效,比如頒發機構,過期時間等等,如果發現異常,則會彈出一個警告框,提示證書存在問題。如果證書沒有問題,那么就生成一個隨即值(預主秘鑰)。
  5. 客戶端認證證書通過之后,接下來是通過隨機值1、隨機值2和預主秘鑰組裝會話秘鑰。然后通過證書的公鑰加密會話秘鑰。
  6. 傳送加密信息,這部分傳送的是用證書加密后的會話秘鑰,目的就是讓服務端使用秘鑰解密得到隨機值1、隨機值2和預主秘鑰。
  7. 服務端解密得到隨機值1、隨機值2和預主秘鑰,然后組裝會話秘鑰,跟客戶端會話秘鑰相同。
  8. 客戶端通過會話秘鑰加密一條消息發送給服務端,主要驗證服務端是否正常接受客戶端加密的消息。
  9. 同樣服務端也會通過會話秘鑰加密一條消息回傳給客戶端,如果客戶端能夠正常接受的話表明SSL層連接建立完成了。
  • 怎么保證保證服務器給客戶端下發的公鑰是真正的公鑰,而不是中間人偽造的公鑰呢?


    認證公鑰
  • 證書如何安全傳輸,被掉包了怎么辦?


    校驗CA證書

4. HTTPS 中使用的自簽名證書生成,配置

  • 數字證書內容

包括了加密后服務器的公鑰、權威機構的信息、服務器域名,還有經過CA私鑰簽名之后的證書內容(經過先通過Hash函數計算得到證書數字摘要,然后用權威機構私鑰加密數字摘要得到數字簽名),簽名計算方法以及證書對應的域名。

  • 驗證證書安全性過程
  1. 當客戶端收到這個證書之后,使用本地配置的權威機構的公鑰對證書進行解密得到服務端的公鑰和證書的數字簽名,數字簽名經過CA公鑰解密得到證書信息摘要。
  2. 然后證書簽名的方法計算一下當前證書的信息摘要,與收到的信息摘要作對比,如果一樣,表示證書一定是服務器下發的,沒有被中間人篡改過。因為中間人雖然有權威機構的公鑰,能夠解析證書內容并篡改,但是篡改完成之后中間人需要將證書重新加密,但是中間人沒有權威機構的私鑰,無法加密,強行加密只會導致客戶端無法解密,如果中間人強行亂修改證書,就會導致證書內容和證書簽名不匹配。
  • 第三方攻擊者能否讓自己的證書顯示出來的信息也是服務端呢?

(偽裝服務端一樣的配置)顯然這個是不行的,因為當第三方攻擊者去CA那邊尋求認證的時候CA會要求其提供例如域名的whois信息、域名管理郵箱等證明你是服務端域名的擁有者,而第三方攻擊者是無法提供這些信息所以他就是無法騙CA他擁有屬于服務端的域名

  • 中間人攻擊(MITM攻擊)
  1. 中間人攻擊(MITM攻擊)是指,黑客攔截并篡改網絡中的通信數據。又分為被動MITM和主動MITM,被動MITM只竊取通信數據而不修改,而主動MITM不但能竊取數據,還會篡改通信數據。最常見的中間人攻擊常常發生在公共wifi或者公共路由上。
  2. HTTPS協議的加密范圍也比較有限,在黑客攻擊、拒絕服務攻擊、服務器劫持等方面幾乎起不到什么作用
    SSL證書的信用鏈體系并不安全,特別是在某些國家可以控制CA根證書的情況下,中間人攻擊一樣可行
  • HTTPS的一些缺點
  1. SSL證書需要購買申請,功能越強大的證書費用越高
  2. SSL證書通常需要綁定IP,不能在同一IP上綁定多個域名,IPv4資源不可能支撐這個消耗(SSL有擴展可以部分解決這個問題,但是比較麻煩,而且要求瀏覽器、操作系統支持,Windows XP就不支持這個擴展,考慮到XP的裝機量,這個特性幾乎沒用)。
  3. 根據ACM CoNEXT數據顯示,使用HTTPS協議會使頁面的加載時間延長近50%,增加10%到20%的耗電。
  4. HTTPS連接緩存不如HTTP高效,流量成本高。
  5. HTTPS連接服務器端資源占用高很多,支持訪客多的網站需要投入更大的成本。
  6. HTTPS協議握手階段比較費時,對網站的響應速度有影響,影響用戶體驗。比較好的方式是采用分而治之,類似12306網站的主頁使用HTTP協議,有關于用戶信息等方面使用HTTPS。
  • 為啥使用自簽名證書
  1. 這個主要是專業機構認證的CA證書費用很高,一般需要5千美金一年。很多公司承受不了這樣的費用
  2. CA認證證書,客戶端不需要做任何處理就可以訪問,根HTTP一樣使用,但是自簽名證書需要自己實現安全認證后,信任后才能使用。
  3. 蘋果自2017年后要求所有HTTP通訊必須走HTTPS方式,否則不予審核通過。
  4. 對于嵌入式設備和App的通訊使用自簽名證書比較靈活一點。
  5. 自簽證書相對申請CA證書,流程更簡單
  6. 自簽證書同樣可以對數據進行加密
  7. 自簽證書的有效期可以設置很長,免去續簽的麻煩
  8. 自簽證書更方便測試,比如說你想生成多少個不同服務器ip的都可以
  • SSL協議提供的服務主要有哪些?

1)認證用戶和服務器,確保數據發送到正確的客戶機和服務器
2)加密數據以防止數據中途被竊取
3)維護數據的完整性,確保數據在傳輸過程中不被改變

  • SSL證書的作用?
  1. SSL證書是數字證書的一種,類似于駕駛證、護照和營業執照的電子副本。
  2. SSL證書的兩大作用:數據加密和身份認證
  3. SSL 證書遵守 SSL協議,通過在客戶端瀏覽器和Web服務器之間建立一條SSL安全通道
  4. 一個有效、可信的 SSL 數字證書包括一個公共密鑰和一個私用密鑰。公共密鑰用于加密信息,私用密鑰用于解譯加密的信息。因此,瀏覽器指向一個安全域時,SSL 將同步確認服務器和客戶端,并創建一種加密方式和一個唯一的會話密鑰。它們可以啟動一個保證消息的隱私性和完整性的安全會話。
  • 證書相關概念
  1. 證書分為2類:自簽名證書和CA證書。一般自簽名證書不能用來進行身份認證,如果一個server端使用自簽名證書,client端要么被設置為無條件信任任何證書,要么需要將自簽名證書的公鑰和私鑰加入受信任列表。但這樣一來就增加了server的私鑰泄露風險
  2. TLS是傳輸層安全協議(Transport Layer Security)的縮寫,是一種對基于網絡的傳輸的加密協議,可以在受信任的第三方公證基礎上做雙方的身份認證。TLS可以用在TCP上,也可以用在無連接的UDP報文上。協議規定了身份認證、算法協商、密鑰交換等的實現。
  3. HTTPS是在基于TLS/SSL的安全套接字上的的應用層協議,除了傳輸層進行了加密外,其它與常規HTTP協議基本保持一致
  4. 證書是TLS協議中用來對身份進行驗證的機制,是一種數字簽名形式的文件,包含證書擁有者的公鑰及第三方的證書信息。
  5. TLS基于CA的身份認證基本原理是:首先驗證方需要信任CA提供方自己的證書(CAcert),比如證書在操作系統的受信任證書列表中,或者用戶通過“安裝根證書”等方式將 CA的公鑰和私鑰加入受信任列表;然后CA對被驗證方的原始證書進行簽名(私鑰加密),生成最終的證書;驗證方得到最終的證書后,利用CAcert中包含的公鑰進行解密,得到被驗證方的原始證書。
  6. 根據RSA的加密原理,如果用CA的公鑰解密成功,說明該證書的確是用CA的私鑰加密的,可以認為被驗證方是可信的。
  7. 自簽名的證書無法被吊銷,CA簽名的證書可以被吊銷 能不能吊銷證書的區別在于,如果你的私鑰被黑客獲取,如果證書不能被吊銷,則黑客可以偽裝成你與用戶進行通信
  8. 如果你的規劃需要創建多個證書,那么使用私有CA的方法比較合適,因為只要給所有的客戶端都安裝了CA的證書,那么以該證書簽名過的證書,客戶端都是信任的,也就是安裝一次就夠了
  9. 如果你直接用自簽名證書,你需要給所有的客戶端安裝該證書才會被信任,如果你需要第二個證書,則還的挨個給所有的客戶端安裝證書2才會被信任。
  • 證書類型:

x509的證書編碼格式有兩種:

  1. PEM(Privacy-enhanced Electronic Mail) 是明文格式的 以 -----BEGIN CERTIFICATE-----開頭,已-----END CERTIFICATE-----結尾,中間是經過base64編碼的內容,apache需要的證書就是這類編碼的證書 查看這類證書的信息的命令為 :openssl x509 -noout -text -in server.pem
    其實PEM就是把DER的內容進行了一次base64編碼
  2. DER 是二進制格式的證書 查看這類證書的信息的命令為 :openssl x509 -noout -text -inform der -in server.der
  • 證書擴展名:
  1. .crt 證書文件 ,可以是DER(二進制)編碼的,也可以是PEM( ASCII (Base64) )編碼的 ,在類unix系統中比較常見
  2. .cer 也是證書 常見于Windows系統 編碼類型同樣可以是DER或者PEM的,windows 下有工具可以轉換crt到cer
  3. .csr 證書簽名請求 一般是生成請求以后發送給CA,然后CA會給你簽名并發回證書
  4. .key 一般公鑰或者密鑰都會用這種擴展名,可以是DER編碼的或者是PEM編碼的 查看DER編碼的(公鑰或者密鑰)的文件的命令為 openssl rsa -inform DER -noout -text -in xxx.key 查看PEM編碼的(公鑰或者密鑰)的文件的命令為 openssl rsa -inform PEM -noout -text -in xxx.key
  5. .p12 證書 包含一個X509證書和一個被密碼保護的私鑰
  • 關于CA 簽名SSL證書

相對自簽證書的自己給自己頒證,由權威的證書授權機構(Certificate Authority)頒發的簽名證書,我們稱之為:CA證書
CA證書保證書持有者的身份和公鑰的擁有權
瀏覽器對CA證書是信任的

4.1 CA證書申請

  • 有很多網站能申請CA證書,如沃通,騰訊,阿里云等,大家可根據自己的喜好去申請
    CA證書又分免費和不同價錢的,當然一分錢一分貨,對于我們個人開發者來說,免費的CA證書就足夠了

4.1.1 從阿里云申請CA證書

  • 1:找到阿里云的CA證書
    打開阿里云主頁:https://www.aliyun.com/,選“產品”再選“CA證書”如下圖:
    找到阿里云的CA證書
  • 2:選擇:立即購買
  • 3:選擇免費型DV SSL(最主要是不用錢呵 :p),點立即購買,如下圖:


    選擇免費型DV SSL
  • 4:點“確認訂單”->”去支付“
  • 5:點”證書控制臺“
  • 6:點如下圖的”補全“,然后填寫個人資料


    點如下圖的”補全“
  • 7:信息補全后點提交,提交后大概一小時左右就能收到證書申請成功的信息,接下來就下載證書:
    去到:”管理控制臺“->”產品與服務”->”我的證書“,選擇”下載”


    信息補全后點提交
  • 8:阿里云能根據不同的服務器生成不同的證書,如tomcat,apache等,選擇自己所要的,如下圖:


    阿里云能根據不同的服務器生成不同的證書

4.1.2

4.1.3

4.2 window生成自簽名證書

keytool -genkey -alias tomcat  -storetype PKCS12 -keyalg RSA -keysize 2048  -keystore d:\mykeystore\keystore.p12 -validity 3650  -ext san=ip:192.168.100.132 -dname "CN=garyyan, OU=mycompany, O=mycompany, L=gd, ST=gd, C=china"

此命令中間只需要輸入密碼,就能生成keystore,假設密碼是:123456
其中:
1)keystore可理解為一個數據庫,可以存很多個組數據。
每組數據主要包含下面兩種數據:
a:密鑰實體(Key entity)——密鑰(secret key)又或者是私鑰和配對公鑰(采用非對稱加密)
b:可信任的證書實體(trusted certificate entries)——只包含公鑰
2)-keystore d:\mykeystore\keystore.p12,指定在d:\mykeystore(先要手動創建此文件夾),生成keystore:keystore.p12
3)-alias tomcat,為其指明在keystore中的唯一的別名:tomcat ,因為keystore中可能還存有其它的別名,如:tomcat 2
4)-storetype PKCS12指明密鑰倉庫類型是PKCS12
5)-keyalg RSA,指定加密算法,本例中的采用通用的RAS加密算法
6)-keysize 2048指定密鑰的長度為2048
7)-validity 3650 指定證書的有效期為3650天
8)-ext san=ip:192.168.100.132請根據你的服務器的IP地址設置,如果不進行設置,客戶端在訪問的時候可能會報錯
9)-dname “CN=garyyan, OU=mycompany,O=mycompany,L=gd, ST=gd, C=china”
其中:”CN=(名字與姓氏), OU=(組織單位名稱), O=(組織名稱), L=(城市或區域名稱), ST=(州或省份名稱), C=(單位的兩字母國家代碼)”,我在測試的過程中發現隨便填就行

  • 4:導出公鑰證書(主要用于客戶端):
    運行命令:
keytool -export -keystore d:\mykeystore\keystore.p12 -alias tomcat -file mycer.cer -storepass 123456

其中:
1)-keystore d:\mykeystore\keystore.p12 是指上面的keystore文件
2)-alias tomcat是指定別名為tomcat的那一組
3)-file mycer.cer指定在當前目錄生成名為mycer.cer的證書
4)-storepass 123456是上面生成keystore 所用的密碼

4.3 mac生成自簽名證書

4.3.1 mac下通過keytool生成自簽名證書

  • 首先需要知道jdk安裝目錄,在terminal下輸入: /usr/libexec/java_home -V

    查看jdk版本

  • 2.跳轉到jdk目錄下


    跳轉到jdk目錄下
  • 輸入keytool查看


    輸入keytool查看
  • 3.創建簽名:終端輸入,keytool -genkey -v -keystore myKey.jks -keyalg RSA -keysize 2048 -validity 10000 -alias myAlias 由于需要權限,執行命令時需要在前面加上sudo

    執行1

  • 按提示輸入相關信息,這里會提示要輸入密碼,我使用的都是相同的密碼123456


    按提示輸入相關信息
  • 如果前面執行keytool -genkey -v -keystore myKey.jks -keyalg RSA -keysize 2048 -validity 10000 -alias myAlias命令時,沒有輸入sudo,則會報下面的錯誤:

    沒有輸入sudo,則會報下面的錯誤

  • 輸入sudo和密碼后執行結果如下:


    輸入sudo和密碼后執行結果如下
  • 查看keystore的指紋數據:keytool -v -list -keystore myKey.jks -alias myAlias -keypass 123456 -storepass 123456

    在這里插入圖片描述

  • 導出證書certificate.pem: sudo keytool -export -rfc -alias myAlias -file upload_certificate.pem -keystore myKey.jks, 這里同樣有權限問題,需要使用sudo

    導出證書certificate.pem

4.3.2 mac下通過openssl生成自簽名證書

4.4 nginx服務器配置自簽名證書

4.5 tomcat服務器配置自簽名證書

4.6 appache服務器配置自簽名證書

5. HTTPS 自己實現IOS端證書驗證

6. Alamofire實現SSL安全認證 源碼解析

7. HTTPS實現文件上傳

8. HTTPS實現文件下載

9. HTTPS文件傳輸通過moya+alamofire+rxswift實現

參考文獻:

  1. http://www.lxweimin.com/p/31bcddf44b8d
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,443評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,530評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,407評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,981評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,759評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,204評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,263評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,415評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,955評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,650評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,892評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,675評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,967評論 2 374

推薦閱讀更多精彩內容