一:HTTPS
HTTPS就是將HTTP協(xié)議數(shù)據(jù)包放到SSL/TSL層加密后,在TCP/IP層組成IP數(shù)據(jù)報去傳輸,以此保證傳輸數(shù)據(jù)的安全擒抛;而對于接收端,在SSL/TSL將接收的數(shù)據(jù)包解密之后补疑,將數(shù)據(jù)傳給HTTP協(xié)議層歧沪,就是普通的HTTP數(shù)據(jù)。HTTP和SSL/TSL都處于OSI模型的應(yīng)用層莲组。
二:App Transport Security
WWDC 15 提出的 ATS (App Transport Security) 是 Apple 在推進網(wǎng)絡(luò)通訊安全的一個重要方式诊胞。在 iOS 9 和 OS X 10.11 中,默認(rèn)情況下非 HTTPS 的網(wǎng)絡(luò)訪問是被禁止的锹杈。當(dāng)然撵孤,因為這樣的推進影響面非常廣,作為緩沖竭望,我們可以在 Info.plist 中添加 NSAppTransportSecurity 字典并且將 NSAllowsArbitraryLoads 設(shè)置為 YES 來禁用 ATS邪码。
不過,WWDC 16 中咬清,Apple 表示將繼續(xù)在 iOS 10 和 macOS 10.12 里收緊對普通 HTTP 的訪問限制闭专。從 2017 年 1 月 1 日起糕韧,所有的新提交 app 默認(rèn)是不允許使用 NSAllowsArbitraryLoads 來繞過 ATS 限制的,也就是說喻圃,我們最好保證 app 的所有網(wǎng)絡(luò)請求都是 HTTPS 加密的,否則可能會在應(yīng)用審核時遇到麻煩粪滤。雖然昨天Apple通知ATS的限制推遲斧拍,但這事遲早都得做。
(蘋果對ATS要求:)
Requirements for Connecting Using ATS
With App Transport Security (ATS) fully enabled, the system requires that your app’s HTTP connections use HTTPS and that they satisfy the following security requirements:
? The X.509 digital server certificate must meet at least one of the following trust requirements:
? Issued by a certificate authority (CA) whose root certificate is incorporated into the operating system
? Issued by a trusted root CA and installed by the user or a system administrator
? The negotiated Transport Layer Security (TLS) version must be TLS 1.2. Attempts to connect without TLS/SSL protection, or with an older version of TLS/SSL, are denied by default.
? The connection must use either the AES-128 or AES-256 symmetric cipher. The negotiated TLS connection cipher suite must support perfect forward secrecy (PFS) through Elliptic Curve Diffie-Hellman Ephemeral (ECDHE) key exchange, and must be one of the following:
? TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
? TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
? TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
? TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
? TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
? TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
? TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
? TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
? TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
? TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
? TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
? The leaf server certificate must be signed with one of the following types of keys:
? Rivest-Shamir-Adleman (RSA) key with a length of at least 2048 bits
? Elliptic-Curve Cryptography (ECC) key with a size of at least 256 bits
In addition, the leaf server certificate hashing algorithm must be Secure Hash Algorithm 2 (SHA-2) with a digest length, sometimes called a “fingerprint,” of at least 256 (that is, SHA-256 or greater).
The requirements listed in this section are current as of this document’s publication date, with stricter requirements possible in the future. Changes to these requirements will not break app binary compatibility.
三:服務(wù)器自簽名證書生成與配置
1.openssl生成證書
第一步杖小,為服務(wù)器端和客戶端準(zhǔn)備公鑰肆汹、私鑰
//生成服務(wù)器端私鑰
openssl genrsa -out server.key 2048
// 生成服務(wù)器端公鑰
openssl rsa -in server.key -pubout -out server.pem
第二步,生成 CA 證書
//生成 CA 私鑰
openssl genrsa -out ca.key 2048
// 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
第三步予权,生成服務(wù)器端證書
//服務(wù)器端需要向 CA 機構(gòu)申請簽名證書昂勉,在申請簽名證書之前依然是創(chuàng)建自己的 CSR 文件
openssl req -new -key server.key -out server.csr
//向自己的 CA 機構(gòu)申請證書,簽名過程需要 CA 的證書和私鑰參與扫腺,最終頒發(fā)一個帶有 CA 簽名的證書
openssl x509 -req -CA ca.crt -CAkey ca.key -CAcreateserial -in server.csr -out server.cr
第四步岗照,生成cer文件
使用openssl 進行轉(zhuǎn)換
openssl x509 -in server.crt -out server.cer -outform der
2.Nginx htts與證書配置
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name example.org;
ssl_certificate /etc/ssl/server.crt ;
ssl_certificate_key /etc/ssl/private/server.key;
ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA;
ssl_prefer_server_ciphers on;
}
3.Tomcat https與證書配置
使用OpenSSL生成的數(shù)字證書和私鑰,如需要在Java或Tomcat環(huán)境下使用笆环,需要先裝其轉(zhuǎn)換成PKCS#12編碼格式的密鑰庫攒至,才能使用keytool工具進行相應(yīng)的管理。轉(zhuǎn)換命令如下:
openssl pkcs12 -export -clcerts -inkey private/client-key.pem -in certs/client.cer -out client.p12
openssl pkcs12 -export -clcerts -inkey private/server-key.pem -in certs/server.cer -out server.p12
打開tomcat的配置文件 vim conf/server.xml
<Connector port="8443" protocol="HTTP/1.1"
maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS"
keystoreFile="/usr/local/ssl/server.p12"
keystoreType="pkcs12"
keystorePass="12345678"
四:App使用HTTPS步驟
1.檢測站點https://m-dev.ws.cn/是否符合ATS要求
-使用命令
nscurl --ats-diagnostics --verbose https://m-dev.ws.cn/
-或者用騰訊云檢測https://www.qcloud.com/product/ssl
(目前有一項還不符合躁劣,但親測不影響使用迫吐,估計跟自建證書有關(guān))
2.將服務(wù)器端給的crt證書轉(zhuǎn)成cer
openssl x509 -in server.crt -out server.cer -outform der
3.修改AFNetWorking請求http的方法,加證書驗證
+ (AFSecurityPolicy*)customSecurityPolicy
{
// /先導(dǎo)入證書
NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"m" ofType:@"cer"];//證書的路徑
NSData *certData = [NSData dataWithContentsOfFile:cerPath];
// AFSSLPinningModeCertificate 使用證書驗證模式
AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
// allowInvalidCertificates 是否允許無效證書(也就是自建的證書)账忘,默認(rèn)為NO
// 如果是需要驗證自建證書志膀,需要設(shè)置為YES
securityPolicy.allowInvalidCertificates = YES;
//validatesDomainName 是否需要驗證域名,默認(rèn)為YES鳖擒;
//假如證書的域名與你請求的域名不一致溉浙,需把該項設(shè)置為NO;如設(shè)成NO的話蒋荚,即服務(wù)器使用其他可信任機構(gòu)頒發(fā)的證書放航,也可以建立連接,這個非常危險圆裕,建議打開广鳍。
//置為NO,主要用于這種情況:客戶端請求的是子域名吓妆,而證書上的是另外一個域名赊时。因為SSL證書上的域名是獨立的,假如證書上注冊的域名是www.google.com行拢,那么mail.google.com是無法驗證通過的祖秒;當(dāng)然,有錢可以注冊通配符的域名*.google.com,但這個還是比較貴的竭缝。
//如置為NO房维,建議自己添加對應(yīng)域名的校驗邏輯。
securityPolicy.validatesDomainName = NO;
securityPolicy.pinnedCertificates = @[certData];
return securityPolicy;
}
4.info.plist中將NSAllowsArbitraryLoads的配置去掉抬纸,即不繞過蘋果的ats限制
但需要對webview和又拍云相關(guān)請求設(shè)置例外(這個蘋果審核可能還存在風(fēng)險咙俩,如果有問題,到時候再修改)
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoadsInWebContent</key>
<true/>
<key>NSExceptionDomains</key>
<dict>
<key>v0.api.upyun.com</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSThirdPartyExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
<false/>
</dict>
<key>voice.b0.upaiyun.com</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSThirdPartyExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
<false/>
</dict>
<key>mage.b0.upaiyun.com</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSThirdPartyExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
<false/>
</dict>
<key>http://voice-group.b0.upaiyun.com</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSThirdPartyExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
<false/>
</dict>
<key>http://image-group.b0.upaiyun.com</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSThirdPartyExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
<false/>
</dict>
</dict>
</dict>