在WWDC 2016開發(fā)者大會(huì)上药版,蘋果宣布了一個(gè)最后期限:到2017年1月1日 App Store中的所有應(yīng)用都必須啟用 App Transport Security安全功能。也就是說(shuō)撒会,自2017年起唠亚,網(wǎng)絡(luò)請(qǐng)求必須由http改成https盖文。正因?yàn)檫@個(gè)原因砍濒,我也打算嘗試下適配Https網(wǎng)絡(luò)請(qǐng)求废士。由于先前沒有配置服務(wù)器經(jīng)驗(yàn)叫潦,網(wǎng)上說(shuō)的也很不詳細(xì),因此踩了不少坑官硝,足足花了一天的時(shí)間〈H铮現(xiàn)在我把我配置的流程寫下來(lái),希望后來(lái)人能少走點(diǎn)彎路氢架。(網(wǎng)上教程有傻咖,但是寫得很亂,難理解岖研,這里我打算用最通俗的語(yǔ)言
來(lái)描述卿操。)
概念誤區(qū):HTTPS和語(yǔ)言無(wú)關(guān)
一開始,我以為https應(yīng)該像處理http報(bào)頭一樣孙援,要寫什么PHP代碼(服務(wù)器語(yǔ)言是PHP),把客戶端傳來(lái)的證書經(jīng)過處理驗(yàn)證什么的害淤,然后再返回處理結(jié)果(類似于Token驗(yàn)證)。因此拓售,一開始我就搜PHP怎么處理HTTPS請(qǐng)求
窥摄,結(jié)果都是介紹怎么用PHP發(fā)送HTTPS請(qǐng)求
的。經(jīng)過一段時(shí)間糾結(jié)邻辉,我才意識(shí)到HTTPS的處理并不需要PHP做什么溪王,你的服務(wù)器(比如apache)就已經(jīng)幫你做好驗(yàn)證了腮鞍,你只需要像接收http請(qǐng)求一樣處理數(shù)據(jù)就可以了,也就是說(shuō)莹菱,服務(wù)器增加HTTPS并不需要在代碼中做什么移国,只要服務(wù)器配置下就好
。
關(guān)于HTTPS握手流程我覺得還是應(yīng)該了解下道伟,可以參考這份資料:https握手流程迹缀。
簡(jiǎn)單得說(shuō)就是客戶端向服務(wù)器發(fā)起需求 ,服務(wù)器把證書發(fā)給客戶端蜜徽,客戶端驗(yàn)證下證書是否合法祝懂,然后用證書的數(shù)據(jù)加密傳輸數(shù)據(jù)給服務(wù)器,服務(wù)器解密
拘鞋。
生成證書文件
看了上面的原理就知道砚蓬,要HTTPS傳輸首先得有證書。在生成證書這方面我也遇到了很大的坑盆色,幾乎所有的網(wǎng)站都要生成2個(gè)證書灰蛙,server.pem
和client.pem
。一開始我把server.pem
配置到服務(wù)器上隔躲,把client.pem
給AFNetwoking,結(jié)果怎么都通過不了驗(yàn)證摩梧!后來(lái)我發(fā)現(xiàn)只要AFNetworing使用server.pem
驗(yàn)證就可以了,也就是說(shuō)只要一份證書就行了宣旱。仅父。。(真的不知道為什么要2份證書浑吟,如有大神歡迎指出)笙纤。
下面我將命令行代碼貼出來(lái),主要參考這篇文章:參考文章
//第一步买置,為服務(wù)器端和客戶端準(zhǔn)備公鑰粪糙、私鑰
# 生成服務(wù)器端私鑰
openssl genrsa -out server.key 1024
# 生成服務(wù)器端公鑰
openssl rsa -in server.key -pubout -out server.pem
//第二步,生成 CA 證書
# 生成 CA 私鑰
openssl genrsa -out ca.key 1024
# X.509 Certificate Signing Request (CSR) Management.
openssl req -new -key ca.key -out ca.csr
# X.509 Certificate Data Management.
openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt
在第二步時(shí)會(huì)出來(lái)一個(gè)填寫資料的界面(我已經(jīng)填好大家可以參考忿项,有些地方可以空著)
Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:Zhejiang
Locality Name (eg, city) []:Hangzhou
Organization Name (eg, company) [Internet Widgits Pty Ltd]:My CA
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:localhost
Email Address []:
這里有點(diǎn)要注意蓉冈, Common Name (e.g. server FQDN or YOUR name) []:
這一項(xiàng),是最后可以訪問的域名轩触,我這里為了方便測(cè)試寞酿,寫成 localhost ,如果是為了給網(wǎng)站生成證書脱柱,需要寫成 xxxx.com 伐弹。
//第三步,生成服務(wù)器端證書
# 服務(wù)器端需要向 CA 機(jī)構(gòu)申請(qǐng)簽名證書榨为,在申請(qǐng)簽名證書之前依然是創(chuàng)建自己的 CSR 文件
openssl req -new -key server.key -out server.csr
# 向自己的 CA 機(jī)構(gòu)申請(qǐng)證書惨好,簽名過程需要 CA 的證書和私鑰參與煌茴,最終頒發(fā)一個(gè)帶有 CA 簽名的證書
openssl x509 -req -CA ca.crt -CAkey ca.key -CAcreateserial -in server.csr -out server.cr
同樣會(huì)有信息填寫,照舊寫就好了日川。
第四步蔓腐,生成cer文件
使用openssl 進(jìn)行轉(zhuǎn)換
openssl x509 -in server.crt -out server.cer -outform der
如果完成,就會(huì)得到這么多文件
配置服務(wù)器
為了方便龄句,我是以mac本地電腦做服務(wù)器回论,使用的是XAMPP搭建的服務(wù)器使用的是apache。在其他服務(wù)器上應(yīng)該就是文件路徑位置不一樣分歇,其他應(yīng)該是一樣的傀蓉。如果有些服務(wù)器沒開啟ssl,可以網(wǎng)上搜索怎么開啟职抡。
修改httpd-ssl.conf文件 把server.crt和server.key的路徑修改對(duì)就好了
SSLCertificateFile /apache/conf/server.crt
SSLCertificateKeyFile /apache/conf/server.key
由于我的服務(wù)器默認(rèn)開啟ssl葬燎,因此我就修改下證書路徑就好了。
我們來(lái)瀏覽器訪問下
按我標(biāo)出的框來(lái)訪問證書缚甩,就可以看見我們剛才自己填的數(shù)據(jù)
因?yàn)椴煌?wù)器配置不同萨蚕,不能一概而論,所以大家還是根據(jù)自己服務(wù)器的情況再配置蹄胰。
配置AFNetworking
這里直接上代碼
+ (AFSecurityPolicy*)customSecurityPolicy
{
// /先導(dǎo)入證書
NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"server" ofType:@"cer"];//證書的路徑
NSData *certData = [NSData dataWithContentsOfFile:cerPath];
// AFSSLPinningModeCertificate 使用證書驗(yàn)證模式
AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
// allowInvalidCertificates 是否允許無(wú)效證書(也就是自建的證書),默認(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是無(wú)法驗(yàn)證通過的衷恭;當(dāng)然此叠,有錢可以注冊(cè)通配符的域名*.google.com,但這個(gè)還是比較貴的随珠。
//如置為NO灭袁,建議自己添加對(duì)應(yīng)域名的校驗(yàn)邏輯猬错。
securityPolicy.validatesDomainName = NO;
securityPolicy.pinnedCertificates = @[certData];
return securityPolicy;
}
+ (void)post:(NSString *)url params:(NSDictionary *)params success:(void (^)(id))success failure:(void (^)(NSError *))failure
{
// 1.獲得請(qǐng)求管理者
AFHTTPSessionManager *mgr = [AFHTTPSessionManager manager];
// 2.申明返回的結(jié)果是text/html類型
mgr.responseSerializer = [AFHTTPResponseSerializer serializer];
// 加上這行代碼,https ssl 驗(yàn)證茸歧。
[mgr setSecurityPolicy:[NetworkHelpManager customSecurityPolicy]];
// 3.發(fā)送POST請(qǐng)求
[mgr POST:url parameters:params
success:^(NSURLSessionDataTask *operation, id responseObj) {
if (success) {
success(responseObj);
}
} failure:^(NSURLSessionDataTask *operation, NSError *error) {
if (failure) {
failure(error);
}
}];
}
還要記得把證書添加到項(xiàng)目中來(lái)哦
下面要介紹下證書的驗(yàn)證模式 AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
- AFSSLPinningModeNone
不做任何驗(yàn)證倦炒,只要服務(wù)器返回了證書就通過
- AFSSLPinningModePublicKey
只驗(yàn)證公鑰部分,只要公鑰部分一致就驗(yàn)證通過举娩,如圖所示析校,紅色框起來(lái)的部分只要一致就通過
- AFSSLPinningModeCertificate
除了公鑰外,其他能容也要一致才能通過驗(yàn)證铜涉。
配置結(jié)果
下面我們用Charles抓包看看是否成功加密了智玻。
返回的數(shù)據(jù)依稀能看出我們證書里的內(nèi)容,但是數(shù)據(jù)已經(jīng)加密了芙代。
總結(jié)
配置https其實(shí)并不難吊奢,既然遲早要更新還不如早一點(diǎn)配置好。其實(shí)很多時(shí)候都是我們不愿意做纹烹,而不是不能做页滚。多一點(diǎn)耐心,多一點(diǎn)實(shí)踐铺呵,就能多一點(diǎn)突破裹驰。
我是翻滾的牛寶寶,歡迎大家評(píng)論交流~