iOS 中使用自簽名證書(shū)實(shí)現(xiàn) HTTPS 雙向認(rèn)證

最近項(xiàng)目中,需要使用自簽名的 HTTPS 證書(shū)實(shí)現(xiàn)雙向認(rèn)證誊薄。網(wǎng)上的資料很多履恩,但是存在各種各樣的問(wèn)題,與 iOS 版本呢蔫、ATS 配置 等多方面因素有關(guān)切心。弄好之后先整一份記下來(lái)。完整的內(nèi)容涉及到的內(nèi)容比較多片吊,還是要全面查閱文檔绽昏,本文只記錄最終的結(jié)果,和部分遇到的問(wèn)題俏脊。
  本文中的代碼全谤,在 iOS 8.x 和 iOS 9.x 的模擬器中測(cè)試通過(guò),iOS 10.x 模擬器和真機(jī)中測(cè)試通過(guò)爷贫。

一认然、背景知識(shí)

對(duì)于 HTTPS 認(rèn)證,不管是單向還是雙向漫萄,在客戶(hù)端連接到服務(wù)端時(shí)卷员,會(huì)觸發(fā)客戶(hù)端的 Authroization Challenge(沒(méi)找到太合適的翻譯,暫且理解為授權(quán)質(zhì)詢(xún))回調(diào)腾务,在處理 Authroization Challenge 之后毕骡,得到兩個(gè)值:(不知道怎么翻譯,隨便寫(xiě)下)

  • NSURLSessionAuthChallengeDisposition 處置方式
    • NSURLSessionAuthChallengeUseCredential
      使用指定的憑證,憑證可能為空
    • NSURLSessionAuthChallengePerformDefaultHandling
      忽略憑證挺峡,使用默認(rèn)的質(zhì)詢(xún)處理器
    • NSURLSessionAuthChallengeCancelAuthenticationChallenge
      整個(gè)請(qǐng)求將被取消; 憑證參數(shù)被忽略葵孤。
    • NSURLSessionAuthChallengeRejectProtectionSpace
      這個(gè)挑戰(zhàn)被拒絕,并且應(yīng)該嘗試下一個(gè) Authentication Protection Space橱赠;憑證參數(shù)被忽略尤仍。
  • NSURLCredential * 憑證
    可以根據(jù)回調(diào)時(shí)傳入的信息,自己調(diào)用相關(guān) API 獲取憑證狭姨,也可以自己偽造

將得到的兩個(gè)值宰啦,作為回調(diào)函數(shù)的結(jié)果回傳給系統(tǒng),以完成 Authroization Challenge饼拍。

以上過(guò)程僅是對(duì) iOS 認(rèn)證過(guò)程的分析赡模,不過(guò)個(gè)人認(rèn)為,網(wǎng)絡(luò)模型是一致的师抄,在不同技術(shù)中即便在實(shí)現(xiàn)細(xì)節(jié)上有所差異漓柑,但總體思路還是大同小異的。

二叨吮、服務(wù)端認(rèn)證

對(duì)于采用通過(guò) CA 購(gòu)買(mǎi)的正式證書(shū)辆布,只要沒(méi)有特別要求,手機(jī)端不需要對(duì) Authroization Challenge 做任何處理茶鉴,就可以直接連接锋玲。
  如果是自簽名證書(shū),就需要做一些處理工作涵叮。iOS 8 及其之前的版本比較簡(jiǎn)單惭蹂,而且目前 iOS 8 在市面上的保有量已經(jīng)很少,不做細(xì)致討論割粮。iOS 9+ 之后引入了 ATS盾碗,帶來(lái)的問(wèn)題比較多所以從代碼到配置上都要做相應(yīng)調(diào)整。

1穆刻、白名單方式

步驟一(修改配置 Info.plist):
(1)針對(duì)域名配置

修改 Info.plist置尔,將要訪(fǎng)問(wèn)的域名配置為 NSExceptionAllowsInsecureHTTPLoads,允許不安全的 HTTP 訪(fǎng)問(wèn):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>NSAppTransportSecurity</key>
    <dict>
        <key>NSExceptionDomains</key>
        <dict>
            <key>yourdomain.com</key>
            <dict>
                <key>NSIncludesSubdomains</key>
                <true/>
                <key>NSExceptionAllowsInsecureHTTPLoads</key>
                <true/>
            </dict>
        </dict>
    </dict>
</dict>
</plist>

這里對(duì)于域名的配置氢伟,類(lèi)似是個(gè)白名單的方式,在白名單中的域名幽歼,配置為允許不安全的 HTTPS 連接朵锣。不安全的證書(shū)原因很多,常見(jiàn)的可能是如下原因?qū)е碌模?/p>

  • 其根證書(shū)不被操作系統(tǒng)信任甸私,如:自簽證書(shū)
  • 證書(shū)過(guò)期或被吊銷(xiāo)
  • 證書(shū)域名與實(shí)際域名不匹配



  配置中的 NSIncludesSubdomains 部分诚些,建議把域名寫(xiě)為頂級(jí)域名,然后把 NSIncludesSubdomains 置 為 true 來(lái)包含子域名
  如果是特定的完整域名诬烹,如:www.yourdomain.com 則把 NSIncludesSubdomains 置 為 false砸烦。后面的說(shuō)法,幾次驗(yàn)證的效果不同绞吁。
如果沒(méi)有特別要求幢痘,建議使用第一種做法,寫(xiě)一級(jí)域名家破,然后包含其子域颜说。

(2)最簡(jiǎn)單粗暴的方法
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
    </dict>
</dict>
</plist>

這種方式:

  • 允許非安全的 HTTP 請(qǐng)求,iOS 9+ 默認(rèn)是不允許 HTTP 連接的
  • 對(duì)于所有域名都可以使用自簽名證書(shū)汰聋,不再需要逐個(gè)指定域名
步驟二(修改代碼):

修改代碼:

// 安全策略
// 同瀏覽器行為脆淹,以操作系統(tǒng)規(guī)則對(duì)服務(wù)器證書(shū)
AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
// 不校驗(yàn)域名陪毡,如果需要校驗(yàn)域名,需要采用內(nèi)置證書(shū)的方式
policy.validatesDomainName = NO;
// 允許無(wú)效證書(shū)
policy.allowInvalidCertificates = YES;

// 為 SessionManager 配置安全策略
AFHTTPSessionManager *mgr = [AFHTTPSessionManager manager];
mgr.securityPolicy = policy;

// 重要!W肀睢!設(shè)置緩存策略褒脯,避免緩存
// AFNetworking 的 GET 方法緩存非常明顯虽缕,一旦成功一次,后面就會(huì)直接使用緩存的結(jié)果女淑,即便網(wǎng)絡(luò)訪(fǎng)問(wèn)失敗瞭郑,也能返回成功數(shù)據(jù),會(huì)對(duì)判斷造成誤導(dǎo)鸭你,所以一定要加上這一句G拧!袱巨!
[mgr.requestSerializer setValue:@"no-cache" forHTTPHeaderField:@"Cache-Control"];
// 發(fā)送請(qǐng)求
[mgr GET:...];

重要:
  白名單方式最簡(jiǎn)單阁谆,但是這樣做只建立安全連接,但不會(huì)對(duì)服務(wù)端證書(shū)做校驗(yàn)愉老,比如:不會(huì)校驗(yàn)證書(shū)與域名的一致性场绿。這樣做的問(wèn)題是無(wú)法防御“中間人攻擊”

2嫉入、內(nèi)置證書(shū)方式

(1)基本實(shí)現(xiàn)

白名單的方案不夠安全焰盗,更為安全的做法:采用內(nèi)置證書(shū)的方式,將用于校驗(yàn)的證書(shū)內(nèi)置在客戶(hù)端咒林,不信任除此之外的證書(shū)熬拒。內(nèi)置的證書(shū),可以是服務(wù)端證書(shū)垫竞,或者是用于頒發(fā)服務(wù)端證書(shū)的 CA 的證書(shū)澎粟。具體要看證書(shū)具體的簽發(fā)方式。
  內(nèi)置的方式,是將證書(shū)轉(zhuǎn)為 DER 格式活烙,然后以 .cer 為擴(kuò)展名徐裸,作為資源放到工程中,AFNetworking 就可以自動(dòng)識(shí)別了啸盏。
  同時(shí)重贺,代碼要做如下調(diào)整:

// 安全策略
// 改為 AFSSLPinningModeCertificate
AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
// 指定驗(yàn)證域名。如果訪(fǎng)問(wèn)的域名與證書(shū)域名不一致宫补,則不能通過(guò)
// 如果需要做域名校驗(yàn)檬姥,必須使用 Pinned 方式。白名單方式粉怕,不集成證書(shū)健民,無(wú)法校驗(yàn)域名
policy.validatesDomainName = YES;
// 對(duì)于自簽證書(shū),使用這個(gè)選項(xiàng)
policy.allowInvalidCertificates = YES;
// cerData1贫贝、cerData2 為 NSData秉犹,內(nèi)容為 DER 格式證書(shū)
// 證書(shū)可以是 CA 證書(shū),也可以是服務(wù)端部署的證書(shū)稚晚,這一步可選崇堵,AFN 可以自動(dòng)識(shí)別
policy.pinnedCertificates = [NSSet setWithObjects:cerData1, cerData2, nil];


// 為 SessionManager 配置安全策略
AFHTTPSessionManager *mgr = [AFHTTPSessionManager manager];
mgr.securityPolicy = policy;

[mgr.requestSerializer setValue:@"no-cache" forHTTPHeaderField:@"Cache-Control"];
// 發(fā)送請(qǐng)求
[mgr GET:...];
☆☆☆ 默認(rèn)校驗(yàn)規(guī)則

上面說(shuō)的兩種方式,實(shí)際上都是使用了 AFNetworking 的默認(rèn)校驗(yàn)規(guī)則客燕,并且根據(jù)默認(rèn)規(guī)則做了個(gè)簡(jiǎn)單實(shí)現(xiàn)鸳劳。其規(guī)則是這樣的:
AFNetworking 的 AFSecurityPolicy 類(lèi)有如下方法:

- (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust forDomain:(NSString *)domain

涉及到三個(gè)因素:

  • securityPolicy.allowInvalidCertificates 是否允許無(wú)效證書(shū),個(gè)人理解這里所說(shuō)的無(wú)效證書(shū)也搓,是指類(lèi)似瀏覽器校驗(yàn)行為赏廓,操作系統(tǒng)不認(rèn)的證書(shū)
  • securityPolicy.validatesDomainName 校驗(yàn)域名
  • securityPolicy.SSLPinningMode PinningMode

表面看來(lái)有如下規(guī)律:

  • 如果要使用自簽名證書(shū),必須指定 allowInvalidCertificates = YES;傍妒,否則不能通過(guò)幔摸;
  • 如果 allowInvalidCertificates == YES 并且 SSLPinningMode == AFSSLPinningModeNone,就是說(shuō)只校驗(yàn)服務(wù)端證書(shū)颤练,不管客戶(hù)端內(nèi)置證書(shū)既忆,并指定為允許無(wú)效證書(shū),則可以通過(guò)嗦玖;
  • SSLPinningMode == AFSSLPinningModeCertificate 或 AFSSLPinningModePublicKey 則看本地內(nèi)置證書(shū)與服務(wù)端證書(shū)是否匹配
  • 使用了 AFSSLPinningModeCertificateAFSSLPinningModePublicKey患雇,會(huì)導(dǎo)致客戶(hù)端沒(méi)有內(nèi)置證書(shū)的網(wǎng)站都不能訪(fǎng)問(wèn),如:https://www.baidu.com

默認(rèn)校驗(yàn)規(guī)則總結(jié):
先約定個(gè)幾個(gè)名詞:

正規(guī)證書(shū) <=> 操作系統(tǒng)認(rèn)可 and (域名一致 or 不校驗(yàn)域名)
有效證書(shū) <=> 正規(guī)證書(shū) or 允許非正規(guī)證書(shū)
無(wú)效證書(shū) <=> 操作系統(tǒng)不認(rèn)可 and 不允許非正規(guī)證書(shū)

  • 先檢查 SSLPinningMode踏揣,如果為 AFSSLPinningModeNone庆亡,檢查證書(shū)是否為有效證書(shū)即為校驗(yàn)結(jié)果;
  • 如果 SSLPinningModeAFSSLPinningModeCertificateAFSSLPinningModePublicKey捞稿,檢查證書(shū),如果為無(wú)效證書(shū),校驗(yàn)結(jié)果不通過(guò)娱局;如果為有效證書(shū)彰亥,后續(xù)則根據(jù)本地集成證書(shū)與服務(wù)端證書(shū)一起校驗(yàn)結(jié)果,作為最終校驗(yàn)結(jié)果衰齐。
  • validatesDomainName任斋,只是判定因素之一,雖然影響整體校驗(yàn)結(jié)果耻涛,但不影響校驗(yàn)邏輯废酷。如:雖然證書(shū)合法,指定做域名校驗(yàn)抹缕,但是證書(shū)域名與訪(fǎng)問(wèn)域名不一致澈蟆,結(jié)果是不通過(guò)。

這部分的校驗(yàn)卓研,可以參見(jiàn)官方文檔:Overriding TLS Chain Validation Correctly

(2)個(gè)性化處理:指定身份驗(yàn)證質(zhì)詢(xún)回調(diào)塊

對(duì)于“標(biāo)準(zhǔn)場(chǎng)景”趴俘,達(dá)到可訪(fǎng)問(wèn)的目的,沒(méi)有額外要求奏赘,上述代碼已經(jīng)可以了寥闪。但是對(duì)于需要額外處理的場(chǎng)景,如:失敗的時(shí)候給出對(duì)應(yīng)提示磨淌,需要使用如下方法疲憋,來(lái)指定用于處理授權(quán)質(zhì)詢(xún)的回調(diào)塊:

// AFURLSessionManager 類(lèi)
// 指定用于處理 身份驗(yàn)證質(zhì)詢(xún) 的回調(diào)塊
– setSessionDidReceiveAuthenticationChallengeBlock:

這部分的實(shí)現(xiàn)詳情可以參見(jiàn) AFNetworking 中 AFURLSessionManager.m 文件里如下方法:

// AFURLSessionManager.m
// 處理身份驗(yàn)證質(zhì)詢(xún)
- URLSession:didReceiveChallenge:completionHandler:

在這個(gè)方法中,會(huì)先查看用戶(hù)是否指定了自己的回調(diào)塊梁只,如果指定了就執(zhí)行用戶(hù)自己的回調(diào)塊缚柳,否則執(zhí)行默認(rèn)實(shí)現(xiàn)。編寫(xiě)自己的回調(diào)方法時(shí)敛纲,可以參考默認(rèn)實(shí)現(xiàn)喂击。

注意:默認(rèn)實(shí)現(xiàn)中,只實(shí)現(xiàn)了服務(wù)端驗(yàn)證淤翔。對(duì)于客戶(hù)端驗(yàn)證部分翰绊,只做了如下處理:

*credential = nil;
disposition = NSURLSessionAuthChallengePerformDefaultHandling;

如果要做客戶(hù)端認(rèn)證,重寫(xiě)這部分代碼即可旁壮,后文中會(huì)提到监嗜。

調(diào)試注意事項(xiàng):

測(cè)試時(shí)有一點(diǎn)需要注意,如果使用 GET 方法抡谐,應(yīng)保證每次都真實(shí)發(fā)送了請(qǐng)求裁奇,而不是使用緩存,避免影響測(cè)試效果麦撵」舫Γ坑袄7尽!

  • (推薦)客戶(hù)端處理:Request 的 Header 中音五,指定 Cache-Controlno-cache
  • 處理 URL:為 URL 增加時(shí)間戳
  • 服務(wù)端處理:Response 的 Header 中惫撰,指定 Cache-Controlno-cache
  • iOS 端設(shè)置:指定緩存策略(不推薦)

3、UIWebView

(1)使用 AFNetworking

AFNetworking 提供了 UIWebView+AFNetworking Category躺涝,可以通過(guò)這個(gè)分類(lèi)為 UIWebView 指定 sessionManager厨钻,并調(diào)用新增加的 - loadRequest:MIMEType:textEncodingName:progress:success:failure: 方法來(lái)進(jìn)行加載。但是在 Cordova 這樣的組件中坚嗜,還會(huì)使用 UIWebView 默認(rèn)的 - loadRequest: 方法夯膀,可以配合 Method Swizzling 解決該問(wèn)題。不過(guò)這樣的話(huà)還是有個(gè)問(wèn)題苍蔬,會(huì)導(dǎo)致 UIWebView 的歷史丟失诱建,無(wú)法執(zhí)行“返回”操作,原因是沒(méi)有使用 UIWebView 自己的方法去訪(fǎng)問(wèn)银室。

(2)使用 NSURLProtocol

目前對(duì)于網(wǎng)絡(luò)認(rèn)證相關(guān)的處理涂佃,效果最好、侵入性最小蜈敢、對(duì)已有代碼邏輯影響最小的辜荠,是 NSURLProtocol 方式。這里有個(gè)用于使 UIWebView 支持客戶(hù)端認(rèn)證的插件抓狭,對(duì)于服務(wù)端認(rèn)證一樣有效伯病,參見(jiàn) https://github.com/mwaylabs/cordova-plugin-client-certificate
  題外話(huà)否过,NSURLProtocol 對(duì)于很多特定場(chǎng)景來(lái)說(shuō)更為有效午笛。比如:曾經(jīng)有項(xiàng)目使用了 HTTP Basic Authorization 認(rèn)證。如果不使用 NSURLProtocol 的方案苗桂,可能會(huì)導(dǎo)致以下兩種情況不能通過(guò)認(rèn)證:

  • 302 引發(fā)的跳轉(zhuǎn)不能自動(dòng)帶上認(rèn)證信息
  • Web 頁(yè)面上的 <img>药磺、<script> 標(biāo)簽、CSS煤伟、Ajax 請(qǐng)求不能通過(guò)認(rèn)證

三癌佩、客戶(hù)端認(rèn)證

對(duì)于雙向 HTTPS 認(rèn)證來(lái)說(shuō),服務(wù)端認(rèn)證是基礎(chǔ)便锨。客戶(hù)端認(rèn)證的前提围辙,是先實(shí)現(xiàn)服務(wù)端認(rèn)證,然后在此基礎(chǔ)上做一下補(bǔ)充放案。
  在前文中服務(wù)端授權(quán)質(zhì)詢(xún)處理相關(guān)的描述中姚建,在對(duì)應(yīng)位置寫(xiě)客戶(hù)端認(rèn)證的代碼即可≈ㄑ常客戶(hù)端需要集成 PKCS12 格式的證書(shū)文件(由證書(shū)及其私鑰文件合成)掸冤,代碼中內(nèi)置對(duì)應(yīng)密碼厘托。
  詳見(jiàn)代碼示例 iOSSSLDemo

四贩虾、相關(guān)因素及討論

1催烘、證書(shū)加載

如果使用 AFNetworking 的話(huà)沥阱,加載證書(shū)非常簡(jiǎn)單缎罢,只要把格式為 DER 的證書(shū)(擴(kuò)展名一般為 .cer.der)集成到 Bundle,然后通過(guò)以下代碼來(lái)自動(dòng)加載:

policy.pinnedCertificates = [AFSecurityPolicy certificatesInBundle:[NSBundle mainBundle]];

如果需要在運(yùn)行時(shí)動(dòng)態(tài)加載臨時(shí)獲取的證書(shū)考杉,可以通過(guò)

policy.pinnedCertificates = [NSSet setWithObjects:cerData1, cerData2, nil];

來(lái)實(shí)現(xiàn)策精。其內(nèi)容為證書(shū)的 NSData 組成的 NSSet

2崇棠、證書(shū)的校驗(yàn)

@interface NSURLRequest (SSL)
@end

@implementation NSURLRequest (SSL)

+ (BOOL)allowsAnyHTTPSCertificateForHost:(NSString *)host {
    return YES;
}
@end

這種使用 Category 的寫(xiě)法咽袜,也導(dǎo)致不會(huì)對(duì)證書(shū)進(jìn)行校驗(yàn)。不過(guò)此方法有兩個(gè)問(wèn)題:

  1. 不校驗(yàn)證書(shū)枕稀,導(dǎo)致安全級(jí)別降低询刹,容易被“中間人”方式攻擊;
  2. 此方法為私有方法萎坷,不建議使用凹联。

3、iOS 8

在 iOS 8 中哆档,如果使用 AFNetworking 來(lái)實(shí)現(xiàn)自簽名證書(shū)的認(rèn)證蔽挠,非常簡(jiǎn)單,只要代碼部分按結(jié)論中的描述來(lái)編寫(xiě)即可瓜浸。
  有一點(diǎn)不太確定的澳淑,網(wǎng)上的資料說(shuō)必須加載證書(shū),但是實(shí)際測(cè)試插佛,不加也可以杠巡,這個(gè)可能跟 AFSSLPinningMode 有關(guān)系,不過(guò)由于目前 iOS 8 保有量很少了雇寇,所以不再深入了氢拥。

4、iOS 9+

對(duì)于 iOS 9+ 的情況谢床,蘋(píng)果加入了 ATS兄一,所以必須做 iOS 9 的適配 按照結(jié)論中說(shuō)的,修改 ATS 部分的設(shè)置识腿。

5出革、AFSSLPinningMode

AFSSLPinningMode 是安全策略的模式指定。

#import <Security/Security.h>

typedef NS_ENUM(NSUInteger, AFSSLPinningMode) {
    AFSSLPinningModeNone,    
    //表示不做SSL pinning渡讼,只跟瀏覽器一樣在系統(tǒng)的信任機(jī)構(gòu)列表里驗(yàn)證服務(wù)端返回的證書(shū)骂束。若證書(shū)是信任機(jī)構(gòu)簽發(fā)的就會(huì)通過(guò)耳璧,若是自己服務(wù)器生成的證書(shū),這里是不會(huì)通過(guò)的展箱。

    AFSSLPinningModeCertificate,
    //表示用證書(shū)綁定方式驗(yàn)證證書(shū)旨枯,需要客戶(hù)端保存有服務(wù)端的證書(shū)拷貝,這里驗(yàn)證分兩步混驰,第一步驗(yàn)證證書(shū)的域名/有效期等信息攀隔,第二步是對(duì)比服務(wù)端返回的證書(shū)跟客戶(hù)端返回的是否一致。

    AFSSLPinningModePublicKey,
    //這個(gè)模式同樣是用證書(shū)綁定方式驗(yàn)證栖榨,客戶(hù)端要有服務(wù)端的證書(shū)拷貝昆汹,只是驗(yàn)證時(shí)只驗(yàn)證證書(shū)里的公鑰,不驗(yàn)證證書(shū)的有效期等信息婴栽。

};

四满粗、代碼示例

iOSSSLDemo

五、參考資料

(完)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末愚争,一起剝皮案震驚了整個(gè)濱河市映皆,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌轰枝,老刑警劉巖捅彻,帶你破解...
    沈念sama閱讀 217,907評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異狸膏,居然都是意外死亡沟饥,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)湾戳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)贤旷,“玉大人,你說(shuō)我怎么就攤上這事砾脑∮资唬” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,298評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵韧衣,是天一觀(guān)的道長(zhǎng)盅藻。 經(jīng)常有香客問(wèn)我,道長(zhǎng)畅铭,這世上最難降的妖魔是什么氏淑? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,586評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮硕噩,結(jié)果婚禮上假残,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好辉懒,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,633評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布阳惹。 她就那樣靜靜地躺著,像睡著了一般眶俩。 火紅的嫁衣襯著肌膚如雪莹汤。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,488評(píng)論 1 302
  • 那天颠印,我揣著相機(jī)與錄音纲岭,去河邊找鬼。 笑死嗽仪,一個(gè)胖子當(dāng)著我的面吹牛荒勇,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播闻坚,決...
    沈念sama閱讀 40,275評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼兢孝!你這毒婦竟也來(lái)了窿凤?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,176評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤跨蟹,失蹤者是張志新(化名)和其女友劉穎雳殊,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體窗轩,經(jīng)...
    沈念sama閱讀 45,619評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡夯秃,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,819評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了痢艺。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片仓洼。...
    茶點(diǎn)故事閱讀 39,932評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖堤舒,靈堂內(nèi)的尸體忽然破棺而出色建,到底是詐尸還是另有隱情,我是刑警寧澤舌缤,帶...
    沈念sama閱讀 35,655評(píng)論 5 346
  • 正文 年R本政府宣布箕戳,位于F島的核電站,受9級(jí)特大地震影響国撵,放射性物質(zhì)發(fā)生泄漏陵吸。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,265評(píng)論 3 329
  • 文/蒙蒙 一介牙、第九天 我趴在偏房一處隱蔽的房頂上張望壮虫。 院中可真熱鬧,春花似錦耻瑟、人聲如沸旨指。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,871評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)谆构。三九已至裸扶,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間搬素,已是汗流浹背呵晨。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,994評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留熬尺,地道東北人摸屠。 一個(gè)月前我還...
    沈念sama閱讀 48,095評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像粱哼,于是被迫代替她去往敵國(guó)和親季二。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,884評(píng)論 2 354

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

  • iOS 10 適配 ATS 一. HTTPS 其實(shí)HTTPS從最終的數(shù)據(jù)解析的角度揭措,與HTTP沒(méi)有任何的區(qū)別胯舷,HT...
    made_China閱讀 1,703評(píng)論 0 12
  • SSL/TLS協(xié)議運(yùn)行機(jī)制的概述:http://blog.csdn.net/xiaofei125145/artic...
    zfl1024閱讀 2,256評(píng)論 0 5
  • 7月29日星期六多云。今天是個(gè)好日子绊含,恰逢休息日桑嘶,如果不值班的話(huà)可以在家好好陪陪孩子,可是公司的工作不能不做吧躬充,今...
    璇戎爸爸閱讀 141評(píng)論 0 0
  • 文/孤鳥(niǎo)差魚(yú) 魚(yú)的訴求 是想聽(tīng)你唱首歌 你卻給它說(shuō)了個(gè)鬼故事
    孤鳥(niǎo)差魚(yú)閱讀 298評(píng)論 6 7
  • 下輩子逃顶,我想做一只鳥(niǎo) 翅膀上掛滿(mǎn)月光 嘴里銜著棉花糖 和著風(fēng)鈴歌唱,叮當(dāng)充甚、叮當(dāng) 我要去爬山 我看到一只貓?jiān)诼飞弦哉?..
    玩笑的熊閱讀 397評(píng)論 52 16