iOS 启用Https和调试:配置证书及代码设置

Apple 自ios9发布之后就一直建议大家启用https,曾经一度要求在2015年下半年要求必须启用https,否则会被拒审核。但是后来因为考虑整个行业还没准备好(也可能是为了配合国家网络监控...)放弃了这一强制做法。
最近国际版需要启用https来访问所有接口,对该问题进行了一点研究,发现网上很多教程不写上如何获取对应域名证书的获取过程,以及大家在启用https后不知道如何设置charles进行debug调试。这里做一下记录:

1、获取到站点的证书:

我们可以使用以下openssl命令来获取到服务器的公开二进制证书(以google为例):

openssl s_client -connect www.google.com:443 </dev/null 2>/dev/null | openssl x509 -outform DER > https.cer

冒号中的为命令主要部分。该条命令将会在当前路径下,形成google.com站点的公开二进制证书,命名为https.cer。您可以将www.google.com 替换成您自己的站点以此来获取您自己站点的https.cer。

需要注意的是 针对某些站点 openssl s_client -connect www.google.com:443 会失效,以国际版域名为例:

grants-MacBook-Pro:Downloads grant.zhou$  openssl s_client -connect www.himalaya.com:443 
CONNECTED(00000003)
4479151596:error:140790E5:SSL routines:ssl23_write:ssl handshake failure:s23_lib.c:177:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 307 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : 0000
    Session-ID: 
    Session-ID-ctx: 
    Master-Key: 
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1569321137
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---

国际版网站明明是支持https的,但是这里检查出来却是不支持https,这是为什么呢?最终,我发现这种行为的原因是服务器需要SNI(服务器名称TLS扩展)才能正常工作。

Initially, SSL and TLS were designed to support only one web site per IP endpoint (address and port combination). SNI is a TLS extension that enables use of more than one certificate on the same IP endpoint. TLS clients use the extension to send the desired name, and TLS servers use it to select the correct certificate to respond with. In a nutshell, SNI makes virtual secure hosting possible.

简单的说SNI扩展是允许一个ip绑定多个证书,通常用于虚拟主机,一个物理主机可以虚拟化为多个域名下的不同服务器。
将-servername选项提供给openssl使其成功连接:

grants-MacBook-Pro:~ grant.zhou$ openssl s_client -connect api.himalaya.com:443 -servername api.himalaya.com
CONNECTED(00000003)
depth=3 C = US, O = "The Go Daddy Group, Inc.", OU = Go Daddy Class 2 Certification Authority
verify return:1
depth=2 C = US, ST = Arizona, L = Scottsdale, O = "GoDaddy.com, Inc.", CN = Go Daddy Root Certificate Authority - G2
verify return:1
depth=1 C = US, ST = Arizona, L = Scottsdale, O = "GoDaddy.com, Inc.", OU = http://certs.godaddy.com/repository/, CN = Go Daddy Secure Certificate Authority - G2
verify return:1
depth=0 C = US, ST = California, L = San Francisco, O = "CarGlass, Inc.", CN = *.himalaya.com
verify return:1
---
Certificate chain
 0 s:/C=US/ST=California/L=San Francisco/O=CarGlass, Inc./CN=*.himalaya.com
   i:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certs.godaddy.com/repository//CN=Go Daddy Secure Certificate Authority - G2
 1 s:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certs.godaddy.com/repository//CN=Go Daddy Secure Certificate Authority - G2
   i:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./CN=Go Daddy Root Certificate Authority - G2
 2 s:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./CN=Go Daddy Root Certificate Authority - G2
   i:/C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
 3 s:/C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
   i:/C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIG4TCCBcmgAwIBAgIJAOzIz6nohTXJMA0GCSqGSIb3DQEBCwUAMIG0MQswCQYD
VQQGEwJVUzEQMA4GA1UECBMHQXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTEa
MBgGA1UEChMRR29EYWRkeS5jb20sIEluYy4xLTArBgNVBAsTJGh0dHA6Ly9jZXJ0
cy5nb2RhZGR5LmNvbS9yZXBvc2l0b3J5LzEzMDEGA1UEAxMqR28gRGFkZHkgU2Vj
dXJlIENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTE4MDYwNjAxNDM0NVoX
DTIwMDYwNjAxNDM0NVowbDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3Ju
aWExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xFzAVBgNVBAoTDkNhckdsYXNzLCBJ
bmMuMRcwFQYDVQQDDA4qLmhpbWFsYXlhLmNvbTCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBAOftD0btfns0CPv12kALHnwMiwetLKKfCq5sDiBqaBpbiMRk
Pm86l2qIpni78Q+ntTNS5/EUEp6qgYvQ/42YDxO8nugP92sekm9KkYdK6i5wYQsf
B0HwJ/IoFrHFvWanCg5+fG2M+vUQ+JUUcDKhxWc49rs62fpup973pOaEbETjYEkm
s3pbe81qp28K0niSFsl4jvmyHlUbJhaQvC328kIZCi9RkBRxHfVuFvVv+ISw7wN7
ksEtif0BNmuZsC7QZgYrWcpB0Wu0Bhe0/7eNmg3pwRZlrAvAiy1dChVAP20vmhmu
SJdOmpFGwLLlormLwvSel3GJjZwN8Z+8ITgOt6kCAwEAAaOCAzswggM3MAwGA1Ud
EwEB/wQCMAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA4GA1UdDwEB
/wQEAwIFoDA1BgNVHR8ELjAsMCqgKKAmhiRodHRwOi8vY3JsLmdvZGFkZHkuY29t
L2dkaWcyczItOS5jcmwwXQYDVR0gBFYwVDBIBgtghkgBhv1tAQcXAjA5MDcGCCsG
AQUFBwIBFitodHRwOi8vY2VydGlmaWNhdGVzLmdvZGFkZHkuY29tL3JlcG9zaXRv
cnkvMAgGBmeBDAECAjB2BggrBgEFBQcBAQRqMGgwJAYIKwYBBQUHMAGGGGh0dHA6
Ly9vY3NwLmdvZGFkZHkuY29tLzBABggrBgEFBQcwAoY0aHR0cDovL2NlcnRpZmlj
YXRlcy5nb2RhZGR5LmNvbS9yZXBvc2l0b3J5L2dkaWcyLmNydDAfBgNVHSMEGDAW
gBRAwr0njsw0gzCiM9f7bLPwtCyAzjAnBgNVHREEIDAegg4qLmhpbWFsYXlhLmNv
bYIMaGltYWxheWEuY29tMB0GA1UdDgQWBBSmyRJiqB93KnNKgMB3g4RNyr3YUzCC
AX8GCisGAQQB1nkCBAIEggFvBIIBawFpAHYApLkJkLQYWBSHuxOizGdwCjw1mAT5
G9+443fNDsgN3BAAAAFj0sPOmgAABAMARzBFAiBYG6B7sRlmuIATazT/Z9Cyl9Ve
8arTBZw3UAzuh8MmrwIhANgUZ9LrXfMMCDIJ5UA5hlzS5AO4WQI8l8ejpDnY3jrh
AHYA7ku9t3XOYLrhQmkfq+GeZqMPfl+wctiDAMR7iXqo/csAAAFj0sPTeQAABAMA
RzBFAiBABzkFtWA4HGPhK8bvcBCwv5Y8TB7VgJtGvySoeQzomwIhAIpJPlKjM/kH
Het1cD8sS5Adn1W/+HP/NxwPYRxkWayVAHcAXqdz+d9WwOe1Nkh90EngMnqRmgyE
oRIShBh1loFxRVgAAAFj0sPUQQAABAMASDBGAiEA+RTnuAJQA17YU5ClZpxrcZYW
oUsyXOdAP6/BBayIT7gCIQC7Ixv0use3LffPXPF70AKRoaqovFZi/8+yC/10JPvR
QzANBgkqhkiG9w0BAQsFAAOCAQEAd8b00/8YLy1adejHoh04CpjmqDtSQWYz3Z7l
na+Tt+wk6XYwfr4VP5QdMglCQDfA7GMbM39EW0PE6sNdmGnvfiPIg4BDHL6e4y62
+osalclSkKmalp1E3mEul3Ox+H0iHFc+AKStYdqmyLGjawzehPvGvRSD1PsTYqoT
Km2Z+6+T/PJ/xVzTCnKkstrkMqIE1aFxAtr6ZNB6aNgSG2x5d4j1OrRnDVDinPnO
zXDvb9c2ox15meAH9yLlmDeJoQB6ySuP4b2KIyL2BekPfBSK2ayN2V7pWBMwNhmA
Os4XnyqXm5KeFV4VlxcTn92Y8pEVUCwLg6Wzk9n8SpSCxerjxA==
-----END CERTIFICATE-----
subject=/C=US/ST=California/L=San Francisco/O=CarGlass, Inc./CN=*.himalaya.com
issuer=/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certs.godaddy.com/repository//CN=Go Daddy Secure Certificate Authority - G2
---
No client certificate CA names sent
Peer signing digest: SHA256
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 5861 bytes and written 458 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES128-GCM-SHA256
    Session-ID: 88EC4FC760304DB6CAC5302F7DC9F623B4CD5C6A57727026C1B918537B02635B
    Session-ID-ctx: 
    Master-Key: 53249292D50A3BCC4B78FA6825EC8BE4168F28448F38D0CF379BD17E299D8F144D347227395511A3FFB8650799E014AC
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 300 (seconds)
    TLS session ticket:
    0000 - 49 64 4c 4a 54 62 65 35-77 46 52 6b 4a 54 54 7a   IdLJTbe5wFRkJTTz
    0010 - 51 33 0e 7f 39 5e 60 0b-ee fe 32 a3 10 b0 e4 17   Q3..9^`...2.....
    0020 - e0 a0 e8 f5 82 91 55 d0-29 9f aa a9 1c ea b9 99   ......U.).......
    0030 - 60 a4 fd ca a8 29 13 30-4a f0 a5 87 50 c0 45 f1   `....).0J...P.E.
    0040 - e1 69 11 f7 40 c5 32 de-74 8d 63 d4 cb 43 b2 4d   .i..@.2.t.c..C.M
    0050 - f6 46 10 8f 4d 61 47 db-fc a7 36 8e 21 82 62 3b   .F..MaG...6.!.b;
    0060 - 19 92 ba 28 7f c8 58 24-ca de 46 d7 bb dc 40 a3   ...(..X$..F...@.
    0070 - 6b 0f 13 8f d0 f6 4f 23-88 62 8d 6d 26 ff 50 48   k.....O#.b.m&.PH
    0080 - c1 4d f8 76 c1 3c 07 29-84 21 b1 d5 05 b3 b3 f6   .M.v.<.).!......
    0090 - 58 f3 97 74 0c 24 40 d6-a0 b7 10 e0 40 da bb 8e   X..t.$@.....@...
    00a0 - 2c 89 fd 20 03 f8 2e 8b-9a 7c 40 dd 06 97 bb f7   ,.. .....|@.....

    Start Time: 1569313654
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---

大家也可以在上面的返回看到 -----BEGIN CERTIFICATE----- 和 -----END CERTIFICATE----- 就是himalaya.com https访问时候的公钥,通过 shell openssl x509 -outform DER > https.cer我们可以转换为Xcode支持的证书类型。

2、将证书放进我们的XCode项目工程中:

如上图所示,将我们的https.cer拖到我们的工程Supporting Files中,把 Copy Items if needed 的勾选上。然后把您的Add to targets 选上,点击确定。就完成了证书的导入工作。

3、在我们的代码中使用我们的cer

AFNetworking中的AFSecurityPolicy是主要的类,我们可以这样来使用它(AFNetworking 2.6.0之前):

    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];

    NSString *cerPath                = [[NSBundle mainBundle] pathForResource:@"https" ofType:@"cer"];
    NSData *certData                 = [NSData dataWithContentsOfFile:cerPath];
    AFSecurityPolicy *securityPolicy = [[AFSecurityPolicy alloc] init];
    [securityPolicy setAllowInvalidCertificates:NO];
    [securityPolicy setPinnedCertificates:@[certData]];
    [securityPolicy setSSLPinningMode:AFSSLPinningModeCertificate];
    [securityPolicy setValidatesDomainName:YES];
    [securityPolicy setValidatesCertificateChain:NO];

    manager.securityPolicy = securityPolicy;

解析:
1)新建一个manager, 地球人都知道
2)在mainBundle中寻找我们刚才拖进项目中的https.cer, 并且将相关的数据读取出来
3)新建一个AFSecurityPolicy,并进行相应的配置
4)将这个AFSecurityPolicy 实例赋值给manager

也可以这样来使用:

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; 

AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate]; 
[securityPolicy setAllowInvalidCertificates:NO]; 
[securityPolicy setValidatesDomainName:YES];
[securityPolicy setValidatesCertificateChain:NO]; 

manager.securityPolicy = securityPolicy;

这种方式比前面那种方式要更加简便一些,主要原因在于AFNetworking会自动去搜索mainBundle下的所有cer结尾的文件并放进内存中;再一一对比。因此在代码中可以省略不写。

这样一个网络请求的https的安全策略就配置好了,接下来再说明一下几个AFSecurityPolicy相关的配置
1> SSLPinningMode
SSLPinningMode 定义了https连接时,如何去校验服务器端给予的证书。

typedef NS_ENUM(NSUInteger, AFSSLPinningMode) {
    AFSSLPinningModeNone,
    AFSSLPinningModePublicKey,
    AFSSLPinningModeCertificate,
};

AFSSLPinningModeNone: 代表客户端无条件地信任服务器端返回的证书。
AFSSLPinningModePublicKey: 代表客户端会将服务器端返回的证书与本地保存的证书中,PublicKey的部分进行校验;如果正确,才继续进行。
AFSSLPinningModeCertificate: 代表客户端会将服务器端返回的证书和本地保存的证书中的所有内容,包括PublicKey和证书部分,全部进行校验;如果正确,才继续进行。

2> allowInvalidCertificates
  allowInvalidCertificates 定义了客户端是否信任非法证书。一般来说,每个版本的iOS设备中,都会包含一些既有的CA根证书。如果接收到的证书是iOS信任的CA根证书签名的,那么则为合法证书;否则则为“非法”证书。
  allowInvalidCertificates 就是用来确认是否信任这样的证书的。当然,我们也可以给iOS加入新的信任的CA证书。iOS已有的CA根证书,可以在这里了解到:https://support.apple.com/en-us/HT204132

3> pinnedCertificates
  pinnedCertificates 就是用来校验服务器返回证书的证书。通常都保存在mainBundle 下。通常默认情况下,AFNetworking会自动寻找在mainBundle的根目录下所有的.cer文件并保存在pinnedCertificates数组里,以校验服务器返回的证书。

4> validatesDomainName
  validatesDomainName 是指是否校验在证书中的domain这一个字段。每个证书都会包含一个DomainName, 它可以是一个IP地址,一个域名或者一端带有通配符的域名。如*.google.com, www.google.com 都可以成为这个证书的DomainName。设置validatesDomainName=YES将严格地保证其安全性。

5> validatesCertificateChain
  validatesCertificateChain 指的是是否校验其证书链。
  通常来讲,一个CA证书颁发机构有很多个子机构,用来签发不同用途的子证书,然后这些子证书又再用来签发相应的证书。只有证书链上的证书都正确,CertificateChain才算验证完成。以Google为例:


从上图可以看到,Google.com的证书的根CA证书是GeoTrust Global CA; 而CA并没有直接给google.com签证书,而是先签名了Google Internet Authority G2, 然后G2再签名了google.com。这时候就需要设备中保存有Google Internet Authority G2证书才能通过校验。
  一般来讲,我推荐将validatesCertificateChain设置为NO,因为并不是太有必要做CertificateChain的校验。并且,在AFNetworking 2.6.0中,也正式将validatesCertificateChain拿掉了(https://github.com/AFNetworking/AFNetworking/blob/master/CHANGELOG.md), 其原因也同样为:There was no documented security advantage to pinning against an entire certificate chain。
  因此,在2.6.0之后,可以不管这个字段。而在此之前,从效率上来说,设定为NO会是个比较明智的选择。

做好以上工作后,您应该就可以正常访问您自己的https服务器了。如果还是有问题请检查:
(1)、HTTPS服务器的正确配置。一般来说,可以使用浏览器打开相同页面来查看浏览器上的小锁是否正常。
(2)、是否https.cer正确打包进了项目中。查看第2步中的内容。
(3)、其他。跟帖呗。有问题大家一起交流,共同进步:)

参考文档:
1、https://github.com/AFNetworking/AFNetworking/blob/master/CHANGELOG.md
2、http://nelson.logdown.com/posts/2015/04/29/how-to-properly-setup-afnetworking-security-connection/
3、https://www.jianshu.com/p/4102b817ff2f

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容