AFNetworking 2.x 閱讀筆記(六)

本文主要記錄關(guān)于 AFSecurityPolicy 模塊的相關(guān)內(nèi)容,主要是AFSecurityPolicy.m, 是 HTTPS網(wǎng)絡(luò)請(qǐng)求中的安全模塊.

HTTPS

HTTPs 的基本內(nèi)容可以參考維基百科

其中的身份認(rèn)證的方法是基于公開密鑰加密算法的身份驗(yàn)證是指通信中的雙方分別持有公開密鑰和私有密鑰,由其中的一方采用私有密鑰對(duì)特定數(shù)據(jù)進(jìn)行加密源譬,而對(duì)方采用公開密鑰對(duì)數(shù)據(jù)進(jìn)行解密帖世,如果解密成功缓醋,就認(rèn)為用戶是合法用戶,否則就認(rèn)為是身份驗(yàn)證失敗呕寝。使用基于公開密鑰加密算法的身份驗(yàn)證的服務(wù)有:SSL, 數(shù)字簽名等等。

bangs blog 的解釋以及有兩個(gè)重要的問題如下:

HTTPS連接建立過程大致是,客戶端和服務(wù)端建立一個(gè)連接灿渴,服務(wù)端返回一個(gè)證書,客戶端里存有各個(gè)受信任的證書機(jī)構(gòu)根證書胰舆,用這些根證書對(duì)服務(wù)端返回的證書進(jìn)行驗(yàn)證骚露,經(jīng)驗(yàn)證如果證書是可信任的,就生成一個(gè)pre-master secret缚窿,用這個(gè)證書的公鑰加密后發(fā)送給服務(wù)端棘幸,服務(wù)端用私鑰解密后得到pre-master secret,再根據(jù)某種算法生成master secret倦零,客戶端也同樣根據(jù)這種算法從pre-master secret生成master secret误续,隨后雙方的通信都用這個(gè)master secret對(duì)傳輸數(shù)據(jù)進(jìn)行加密解密吨悍。

以上是簡(jiǎn)單過程,中間還有很多細(xì)節(jié)蹋嵌,詳細(xì)過程和原理已經(jīng)有很多文章闡述得很好育瓜,就不再?gòu)?fù)述,推薦一些相關(guān)文章:
關(guān)于非對(duì)稱加密算法的原理:RSA算法原理<一> <二>
關(guān)于整個(gè)流程:HTTPS那些事<一> <二> <三>
關(guān)于數(shù)字證書:淺析數(shù)字證書

1.證書是怎樣驗(yàn)證的栽烂?怎樣保證中間人不能偽造證書躏仇?

首先要知道非對(duì)稱加密算法的特點(diǎn),非對(duì)稱加密有一對(duì)公鑰私鑰腺办,用公鑰加密的數(shù)據(jù)只能通過對(duì)應(yīng)的私鑰解密焰手,用私鑰加密的數(shù)據(jù)只能通過對(duì)應(yīng)的公鑰解密。
我們來看最簡(jiǎn)單的情況:一個(gè)證書頒發(fā)機(jī)構(gòu)(CA)怀喉,頒發(fā)了一個(gè)證書A书妻,服務(wù)器用這個(gè)證書建立https連接』撬停客戶端在信任列表里有這個(gè)CA機(jī)構(gòu)的根證書驻子。
首先CA機(jī)構(gòu)頒發(fā)的證書A里包含有證書內(nèi)容F,以及證書加密內(nèi)容F1估灿,加密內(nèi)容F1就是用這個(gè)證書機(jī)構(gòu)的私鑰對(duì)內(nèi)容F加密的結(jié)果崇呵。(這中間還有一次hash算法,略過馅袁。)
建立https連接時(shí)域慷,服務(wù)端返回證書A給客戶端,客戶端的系統(tǒng)里的CA機(jī)構(gòu)根證書有這個(gè)CA機(jī)構(gòu)的公鑰汗销,用這個(gè)公鑰對(duì)證書A的加密內(nèi)容F1解密得到F2犹褒,跟證書A里內(nèi)容F對(duì)比,若相等就通過驗(yàn)證弛针。整個(gè)流程大致是:F->CA私鑰加密->F1->客戶端CA公鑰解密->F叠骑。因?yàn)橹虚g人不會(huì)有CA機(jī)構(gòu)的私鑰,客戶端無法通過CA公鑰解密削茁,所以偽造的證書肯定無法通過驗(yàn)證宙枷。

2.什么是SSL Pinning?

可以理解為證書綁定茧跋,是指客戶端直接保存服務(wù)端的證書慰丛,建立https連接時(shí)直接對(duì)比服務(wù)端返回的和客戶端保存的兩個(gè)證書是否一樣,一樣就表明證書是真的瘾杭,不再去系統(tǒng)的信任證書機(jī)構(gòu)里尋找驗(yàn)證诅病。這適用于非瀏覽器應(yīng)用,因?yàn)闉g覽器跟很多未知服務(wù)端打交道,無法把每個(gè)服務(wù)端的證書都保存到本地贤笆,但CS架構(gòu)的像手機(jī)APP事先已經(jīng)知道要進(jìn)行通信的服務(wù)端蝇棉,可以直接在客戶端保存這個(gè)服務(wù)端的證書用于校驗(yàn)。
為什么直接對(duì)比就能保證證書沒問題苏潜?如果中間人從客戶端取出證書银萍,再偽裝成服務(wù)端跟其他客戶端通信,它發(fā)送給客戶端的這個(gè)證書不就能通過驗(yàn)證嗎恤左?確實(shí)可以通過驗(yàn)證,但后續(xù)的流程走不下去搀绣,因?yàn)橄乱徊娇蛻舳藭?huì)用證書里的公鑰加密飞袋,中間人沒有這個(gè)證書的私鑰就解不出內(nèi)容,也就截獲不到數(shù)據(jù)链患,這個(gè)證書的私鑰只有真正的服務(wù)端有巧鸭,中間人偽造證書主要偽造的是公鑰。
為什么要用SSL Pinning麻捻?正常的驗(yàn)證方式不夠嗎纲仍?如果服務(wù)端的證書是從受信任的的CA機(jī)構(gòu)頒發(fā)的,驗(yàn)證是沒問題的贸毕,但CA機(jī)構(gòu)頒發(fā)證書比較昂貴郑叠,小企業(yè)或個(gè)人用戶可能會(huì)選擇自己頒發(fā)證書,這樣就無法通過系統(tǒng)受信任的CA機(jī)構(gòu)列表驗(yàn)證這個(gè)證書的真?zhèn)瘟嗣鞴鳎孕枰猄SL Pinning這樣的方式去驗(yàn)證乡革。

關(guān)于Certificate Pinning

在SSL/TLS通信中,客戶端通過數(shù)字證書判斷服務(wù)器是否可信摊腋,并采用證書的公鑰與服務(wù)器進(jìn)行加密通信.
然而在很多移動(dòng)應(yīng)用中,開發(fā)者不檢查服務(wù)器證書的有效性沸版,或選擇接受所有的證書,這樣就會(huì)導(dǎo)致中間人攻擊.
事實(shí)上,app大多只和固定的服務(wù)器通信,因此可以在代碼更精確地直接驗(yàn)證某張?zhí)囟ǖ淖C書兴蒸,這種方法稱為“證書鎖定”(certificate pinning)

如果進(jìn)行 Certificate Pinning

具體步驟如下:
1 首先通過服務(wù)器端使用RSA算法生成一對(duì)公鑰私鑰對(duì)视粮,服務(wù)器端持有私鑰,線下將公鑰傳給客戶端橙凳。App中將這個(gè)值硬編碼到本地蕾殴。
2 App端可以自己實(shí)現(xiàn)一個(gè)X509TrustManager接口,在其中的CheckServerTrusted()方法里通過證書鏈拿到PublicKey
3 比較12中進(jìn)行md5的值,如果匹配則服務(wù)器驗(yàn)證通過痕惋,否則立即終止與此服務(wù)器的通信.

AFNetworking 就是采用的這種方法.

如果引入第三方的支付等

在實(shí)際應(yīng)用中区宇,一款移動(dòng)應(yīng)用往往不止一個(gè)后臺(tái),尤其是在支付類產(chǎn)品中值戳,經(jīng)常需要去集成第三方支付網(wǎng)關(guān)议谷。

但是第三方的服務(wù)什么時(shí)候會(huì)更改證書,這個(gè)就說不準(zhǔn)了堕虹。初期卧晓,我們會(huì)把所有的這些第三方的服務(wù)提供的PublicKey都硬編碼在本地芬首,但是有次其中一個(gè)服務(wù)商自己改掉了,造成用戶手上的產(chǎn)品直接不能使用了逼裆, 這個(gè)就給我們帶來了不必要的麻煩郁稍。

具體的解決方案如下:
1 自己的服務(wù)端使用RSA算法生成一對(duì)公鑰私鑰對(duì),服務(wù)器端持有私鑰胜宇,線下將公鑰傳給客戶端耀怜。App中將這個(gè)值硬編碼到本地
2 自己的服務(wù)端提供API,獲得當(dāng)前所有服務(wù)器(包括第三方)公鑰的SHASUM值.當(dāng)然這個(gè)值必須通過1中存在本地PublicKey簽名驗(yàn)證得到
3 再通過最基本Certificate Pinning的辦法(上文提到),直接從各服務(wù)端拿到各自公鑰桐愉, 連同本地PublicKey一起計(jì)算SHASUM
4 比較2和3中的值财破,如果相同則Certificate Pinning通過,否則終止app

詳細(xì)的參考資料:
https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning

iOS 中實(shí)現(xiàn)對(duì) HTTPS 的支持

詳細(xì)參考資料: http://oncenote.com/2014/10/21/Security-1-HTTPS/

首先从诲,需要明確你使用HTTP/HTTPS的用途左痢,因?yàn)镺SX和iOS平臺(tái)提供了多種API,來支持不同的用途系洛,官方文檔《Making HTTP and HTTPS Requests》有詳細(xì)的說明俊性,而文檔《HTTPS Server Trust Evaluation》則詳細(xì)講解了HTTPS驗(yàn)證相關(guān)知識(shí),這里就不多說了描扯。主要講解我們最常用的NSURLConnection支持HTTPS的實(shí)現(xiàn)(NSURLSession的實(shí)現(xiàn)方法類似定页,只是要求授權(quán)證明的回調(diào)不一樣而已),以及怎么樣使用AFNetworking這個(gè)非常流行的第三方庫(kù)來支持HTTPS荆烈。

驗(yàn)證證書的API

相關(guān)的Api在Security Framework中拯勉,驗(yàn)證流程如下:

  1. 第一步,先獲取需要驗(yàn)證的信任對(duì)象(Trust Object)憔购。這個(gè)Trust Object在不同的應(yīng)用場(chǎng)景下獲取的方式都不一樣宫峦,對(duì)于NSURLConnection來說,是從delegate方法-connection:willSendRequestForAuthenticationChallenge:
    回調(diào)回來的參數(shù)challenge中獲取([challenge.protectionSpace serverTrust]
    )玫鸟。
  1. 使用系統(tǒng)默認(rèn)驗(yàn)證方式驗(yàn)證Trust Object导绷。SecTrustEvaluate
    會(huì)根據(jù)Trust Object的驗(yàn)證策略,一級(jí)一級(jí)往上屎飘,驗(yàn)證證書鏈上每一級(jí)數(shù)字簽名的有效性(上一部分有講解)妥曲,從而評(píng)估證書的有效性。
  2. 如第二步驗(yàn)證通過了钦购,一般的安全要求下檐盟,就可以直接驗(yàn)證通過,進(jìn)入到下一步:使用Trust Object生成一份憑證([NSURLCredential credentialForTrust:serverTrust]
    )押桃,傳入challenge的sender中([challenge.sender useCredential:cred forAuthenticationChallenge:challenge]
    )處理葵萎,建立連接。
  3. 假如有更強(qiáng)的安全要求,可以繼續(xù)對(duì)Trust Object進(jìn)行更嚴(yán)格的驗(yàn)證羡忘。常用的方式是在本地導(dǎo)入證書谎痢,驗(yàn)證Trust Object與導(dǎo)入的證書是否匹配。更多的方法可以查看Enforcing Stricter Server Trust Evaluation卷雕,這一部分在講解AFNetworking源碼中會(huì)講解到节猿。
  4. 假如驗(yàn)證失敗,取消此次Challenge-Response Authentication驗(yàn)證流程漫雕,拒絕連接請(qǐng)求滨嘱。
    ps: 假如是自建證書的,則不使用第二步系統(tǒng)默認(rèn)的驗(yàn)證方式浸间,因?yàn)樽越ㄗC書的根CA的數(shù)字簽名未在操作系統(tǒng)的信任列表中九孩。
    iOS授權(quán)驗(yàn)證的API和流程大概了解了,下面发框,我們看看在NSURLConnection中的代碼實(shí)現(xiàn):

使用NSURLConnection支持HTTPS的實(shí)現(xiàn)

// Now start the connection
NSURL * httpsURL = [NSURL URLWithString:@"https://www.google.com"];
self.connection = [NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:httpsURL] delegate:self];
//回調(diào)
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
    //1)獲取trust object
    SecTrustRef trust = challenge.protectionSpace.serverTrust;
    SecTrustResultType result;
    
    //2)SecTrustEvaluate對(duì)trust進(jìn)行驗(yàn)證
    OSStatus status = SecTrustEvaluate(trust, &result);
    if (status == errSecSuccess &&
        (result == kSecTrustResultProceed || result == kSecTrustResultUnspecified)) {
            //3)驗(yàn)證成功,生成NSURLCredential憑證cred煤墙,告知challenge的sender使用這個(gè)憑證來繼續(xù)連接
            NSURLCredential *cred = [NSURLCredential credentialForTrust:trust];
            [challenge.sender useCredential:cred forAuthenticationChallenge:challenge];
        } else {
            //5)驗(yàn)證失敗梅惯,取消這次驗(yàn)證流程
            [challenge.sender cancelAuthenticationChallenge:challenge];
    }
}

上面是代碼是通過系統(tǒng)默認(rèn)驗(yàn)證流程來驗(yàn)證證書的。假如我們是自建證書的呢仿野?這樣Trust Object里面服務(wù)器的證書因?yàn)椴皇强尚湃蔚腃A簽發(fā)的铣减,所以直接使用SecTrustEvaluate
進(jìn)行驗(yàn)證是不會(huì)成功。又或者脚作,即使服務(wù)器返回的證書是信任CA簽發(fā)的葫哗,又如何確定這證書就是我們想要的特定證書?這就需要先在本地導(dǎo)入證書球涛,設(shè)置成需要參與驗(yàn)證的Anchor Certificate(錨點(diǎn)證書劣针,通過SecTrustSetAnchorCertificates
設(shè)置了參與校驗(yàn)錨點(diǎn)證書之后,假如驗(yàn)證的數(shù)字證書是這個(gè)錨點(diǎn)證書的子節(jié)點(diǎn)亿扁,即驗(yàn)證的數(shù)字證書是由錨點(diǎn)證書對(duì)應(yīng)CA或子CA簽發(fā)的捺典,或是該證書本身,則信任該證書)从祝,再調(diào)用SecTrustEvaluate
來驗(yàn)證襟己。代碼如下

//先導(dǎo)入證書
NSString * cerPath = ...; //證書的路徑
NSData * cerData = [NSData dataWithContentsOfFile:cerPath];
SecCertificateRef certificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)(cerData));
self.trustedCertificates = @[CFBridgingRelease(certificate)];

//回調(diào)
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
    //1)獲取trust object
    SecTrustRef trust = challenge.protectionSpace.serverTrust;
    SecTrustResultType result;
    
    //注意:這里將之前導(dǎo)入的證書設(shè)置成下面驗(yàn)證的Trust Object的anchor certificate
    SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)self.trustedCertificates);
    
    //2)SecTrustEvaluate會(huì)查找前面SecTrustSetAnchorCertificates設(shè)置的證書或者系統(tǒng)默認(rèn)提供的證書,對(duì)trust進(jìn)行驗(yàn)證
    OSStatus status = SecTrustEvaluate(trust, &result);
    if (status == errSecSuccess &&
        (result == kSecTrustResultProceed ||
         result == kSecTrustResultUnspecified)) {
            //3)驗(yàn)證成功牍陌,生成NSURLCredential憑證cred擎浴,告知challenge的sender使用這個(gè)憑證來繼續(xù)連接
            NSURLCredential *cred = [NSURLCredential credentialForTrust:trust];
            [challenge.sender useCredential:cred forAuthenticationChallenge:challenge];
        } else {
            //5)驗(yàn)證失敗,取消這次驗(yàn)證流程
            [challenge.sender cancelAuthenticationChallenge:challenge];
        }
}

建議采用本地導(dǎo)入證書的方式驗(yàn)證證書毒涧,來保證足夠的安全性贮预。更多的驗(yàn)證方法,請(qǐng)查看官方文檔《HTTPS Server Trust Evaluation》

使用 AFNetworking 的安全設(shè)置

Pinning Mode

AFNetworking 的安全相關(guān)的設(shè)置在AFSecurityPolicy,它定義3種 SSL Pinning Mode:

typedef NS_ENUM(NSUInteger, AFSSLPinningMode) {
    AFSSLPinningModeNone,
    AFSSLPinningModePublicKey,
    AFSSLPinningModeCertificate,
};
  • AFSSLPinningModeNone : 你不必將憑證跟你的 APP 一起打包,完全信任服務(wù)器的憑證
  • AFSSLPinningModeCertificate : 對(duì)比服務(wù)器憑證跟你的憑證是否完全匹配
  • AFSSLPinningModePublicKey : 只對(duì)比服務(wù)器憑證的 publick key跟你的憑證的 public key 是否匹配

那么使用哪種方式比較好?
AFSSLPinningModeCertificate 比較安全同時(shí)比較麻煩, 它會(huì)對(duì)比你打包的憑證和服務(wù)器的憑證是否一致.因?yàn)槟愕膽{證是和 app 一起打包的,這也就代表說如果你的憑證過期或者變化了,你就必須得更新 app,而且舊版 app 無法使用了.當(dāng)然也可以在每次 app 啟動(dòng)時(shí)候就去某個(gè)服務(wù)器下載最新的憑證,不過此時(shí)下載鏈接有風(fēng)險(xiǎn).

AFSSLPinningModePublicKey 則是只有對(duì)比憑證里面的 public key, 所以即使服務(wù)器的憑證有所變動(dòng),只要 public key 沒變化, 就能通過驗(yàn)證

一般情況下使用AFSSLPinningModePublicKey,除非你能保證 app 使用者都只用最新版本的 app.

Certification Chain

/** Whether to evaluate an entire SSL certificate chain, or just the leaf certificate. Defaults to `YES`. */
@property (nonatomic, assign) BOOL validatesCertificateChain;

如果你的憑證是某個(gè)機(jī)構(gòu)發(fā)出的,該機(jī)構(gòu)的憑證是由另外一家更加高級(jí)的機(jī)構(gòu)發(fā)出的,一路往上追,這樣一串由各個(gè)機(jī)構(gòu)發(fā)出的憑證稱為 certification chain.

如果你把這個(gè)屬性設(shè)置為 Yes,那就得把這一串憑證全部打包到你的 APP,必須每個(gè)驗(yàn)證都通過才算通過,如果設(shè)置為 No, 只需要打包你自己的憑證就夠了.

在2.6x 以后的版本的 AFNetworking 以后已經(jīng)沒有 validatesCertificateChain這個(gè)屬性.

參考連接:
http://robnapier.net/pinning-your-ssl-certs
http://stackoverflow.com/questions/24615144/afnetworking-pin-public-key-for-a-trusted-certificate/24625969#24625969
http://oncenote.com/2014/10/21/Security-1-HTTPS/
https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning

AFNetworking 中 HTTPS 實(shí)例

NSURL * url = [NSURL URLWithString:@"https://www.google.com"];
AFHTTPRequestOperationManager * requestOperationManager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:url];
dispatch_queue_t requestQueue = dispatch_create_serial_queue_for_name("kRequestCompletionQueue");
requestOperationManager.completionQueue = requestQueue;

AFSecurityPolicy * securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];

//allowInvalidCertificates 是否允許無效證書(也就是自建的證書)萌狂,默認(rèn)為NO
//如果是需要驗(yàn)證自建證書档玻,需要設(shè)置為YES
securityPolicy.allowInvalidCertificates = YES;

//validatesDomainName 是否需要驗(yàn)證域名,默認(rèn)為YES茫藏;
//假如證書的域名與你請(qǐng)求的域名不一致误趴,需把該項(xiàng)設(shè)置為NO;如設(shè)成NO的話务傲,即服務(wù)器使用其他可信任機(jī)構(gòu)頒發(fā)的證書凉当,也可以建立連接,這個(gè)非常危險(xiǎn)售葡,建議打開缚态。
//置為NO误证,主要用于這種情況:客戶端請(qǐng)求的是子域名,而證書上的是另外一個(gè)域名。因?yàn)镾SL證書上的域名是獨(dú)立的叶骨,假如證書上注冊(cè)的域名是www.google.com,那么mail.google.com是無法驗(yàn)證通過的恢共;當(dāng)然晃听,有錢可以注冊(cè)通配符的域名*.google.com,但這個(gè)還是比較貴的介却。
//如置為NO谴供,建議自己添加對(duì)應(yīng)域名的校驗(yàn)邏輯。
securityPolicy.validatesDomainName = YES;

//validatesCertificateChain 是否驗(yàn)證整個(gè)證書鏈齿坷,默認(rèn)為YES
//設(shè)置為YES桂肌,會(huì)將服務(wù)器返回的Trust Object上的證書鏈與本地導(dǎo)入的證書進(jìn)行對(duì)比,這就意味著永淌,假如你的證書鏈?zhǔn)沁@樣的:
//GeoTrust Global CA
//    Google Internet Authority G2
//        *.google.com
//那么崎场,除了導(dǎo)入*.google.com之外,還需要導(dǎo)入證書鏈上所有的CA證書(GeoTrust Global CA, Google Internet Authority G2)仰禀;
//如是自建證書的時(shí)候照雁,可以設(shè)置為YES,增強(qiáng)安全性答恶;假如是信任的CA所簽發(fā)的證書饺蚊,則建議關(guān)閉該驗(yàn)證,因?yàn)檎麄€(gè)證書鏈一一比對(duì)是完全沒有必要(請(qǐng)查看源代碼)悬嗓;
securityPolicy.validatesCertificateChain = NO;

requestOperationManager.securityPolicy = securityPolicy;

AFSecurity 在源碼中的位置

AFHTTPRequestOperationManager ,AFURLConnectionOperation, 類中有以下屬性

 The security policy used by created request operations to evaluate server trust for secure connections. `AFHTTPRequestOperationManager` uses the `defaultPolicy` unless otherwise specified.
 */
@property (nonatomic, strong) AFSecurityPolicy *securityPolicy;

最后這個(gè)屬性被設(shè)置成AFURLConnectionOperation的以上屬性, 通過該屬性的注釋 -- 用于 request 中驗(yàn)證服務(wù)器身份.

具體使用代碼:

//把服務(wù)端證書(需要轉(zhuǎn)換成cer格式)放到APP項(xiàng)目資源里污呼,AFSecurityPolicy會(huì)自動(dòng)尋找根目錄下所有cer文件,當(dāng)然也可以自己打包到自己的 xxx.bundle 中,但是需要在源碼中進(jìn)行一定的設(shè)置

AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode: AFSSLPinningModePublicKey];
securityPolicy.allowInvalidCertificates = YES;
[AFHTTPRequestOperationManager manager].securityPolicy = securityPolicy;

[manager GET:@"[https://example.com/](https://example.com/)"
    parameters:nil
          success:^(AFHTTPRequestOperation *operation, id, responseObject) {
          } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
}];

具體的源碼注釋可以參考 bangs blog

個(gè)人準(zhǔn)備總結(jié)一份關(guān)于 iOS 可能用到的 HTTPS 相關(guān)的系列文章

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市包竹,隨后出現(xiàn)的幾起案子燕酷,更是在濱河造成了極大的恐慌籍凝,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,454評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件苗缩,死亡現(xiàn)場(chǎng)離奇詭異饵蒂,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)酱讶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門退盯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人泻肯,你說我怎么就攤上這事渊迁。” “怎么了灶挟?”我有些...
    開封第一講書人閱讀 157,921評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵琉朽,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我稚铣,道長(zhǎng)箱叁,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,648評(píng)論 1 284
  • 正文 為了忘掉前任惕医,我火速辦了婚禮蝌蹂,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘曹锨。我一直安慰自己,他們只是感情好剃允,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評(píng)論 6 386
  • 文/花漫 我一把揭開白布沛简。 她就那樣靜靜地躺著,像睡著了一般斥废。 火紅的嫁衣襯著肌膚如雪椒楣。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,950評(píng)論 1 291
  • 那天牡肉,我揣著相機(jī)與錄音捧灰,去河邊找鬼。 笑死统锤,一個(gè)胖子當(dāng)著我的面吹牛毛俏,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播饲窿,決...
    沈念sama閱讀 39,090評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼煌寇,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了逾雄?” 一聲冷哼從身側(cè)響起阀溶,我...
    開封第一講書人閱讀 37,817評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤腻脏,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后银锻,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體永品,經(jīng)...
    沈念sama閱讀 44,275評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評(píng)論 2 327
  • 正文 我和宋清朗相戀三年击纬,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了鼎姐。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,724評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡掉弛,死狀恐怖症见,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情殃饿,我是刑警寧澤谋作,帶...
    沈念sama閱讀 34,409評(píng)論 4 333
  • 正文 年R本政府宣布,位于F島的核電站乎芳,受9級(jí)特大地震影響遵蚜,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜奈惑,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評(píng)論 3 316
  • 文/蒙蒙 一吭净、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧肴甸,春花似錦寂殉、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至庶柿,卻和暖如春村怪,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背浮庐。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工甚负, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人审残。 一個(gè)月前我還...
    沈念sama閱讀 46,503評(píng)論 2 361
  • 正文 我出身青樓梭域,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親搅轿。 傳聞我的和親對(duì)象是個(gè)殘疾皇子碰辅,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評(píng)論 2 350

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