【问题标题】:ios9 self signed certificate and app transport securityios9 自签名证书和应用程序传输安全性
【发布时间】:2016-03-23 12:34:39
【问题描述】:

我花了一段时间试图让它工作。我有一个正在连接的 API,我正在尝试使用自签名证书切换到 SSL。我可以控制服务器和应用程序。

我根据这个生成了一个自签名证书:

https://kyup.com/tutorials/create-ssl-certificate-nginx/

sudo openssl genrsa -des3 -out ssl.key 2048
sudo openssl req -new -key ssl.key -out ssl.csr
sudo cp ssl.key ssl.key.orig & sudo openssl rsa -in ssl.key.orig -out ssl.key
sudo openssl x509 -req -days 365 -in ssl.csr -signkey ssl.key -out ssl.crt

我在服务器 (NGINX) 上尝试了一些配置选项

ssl on;
ssl_certificate /etc/nginx/ssl/ssl.crt;
ssl_certificate_key /etc/nginx/ssl/ssl.key;
ssl_session_timeout 5m;
ssl_protocols  SSLv2 SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
#ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS";
ssl_prefer_server_ciphers on;

在客户端,我尝试了一些使用 ATS 的不同选项:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

和

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
    <key>NSExceptionDomains</key>
    <dict>
        <key>test.example.com (NOT REALLY MY DOMAIN)</key>
        <dict>
            <key>NSExceptionAllowsInsecureHTTPLoads</key>
            <true/>
        </dict>
    </dict>
</dict>

和

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
    <key>NSExceptionDomains</key>
    <dict>
        <key>test.example.com (NOT REALLY MY DOMAIN)</key>
        <dict>
            <key>NSExceptionAllowsInsecureHTTPLoads</key>
            <true/>
            <key>NSExceptionRequiresForwardSecrecy</key>
            <false/>
            <key>NSExceptionMinimumTLSVersion</key>
            <string>TLSv1.1</string>
        </dict>
    </dict>
</dict>

根据不同的 ATS 选项,我会收到错误:

An SSL error has occurred and a secure connection to the server cannot be made.

或

NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9813)
The certificate for this server is invalid. You might be connecting to a server that is pretending to be “MYDOMAIN” which could put your confidential information at risk.

有什么想法吗?还有其他人在为自签名证书而苦恼吗?

附:我使用的是 OS X 10.11.2 Beta,Xcode 7.1.1

【问题讨论】:

    标签: ssl nginx ios9 tls1.2 app-transport-security


    【解决方案1】:

    我发现了这个问题。它与应用程序传输安全无关。我必须确保 iOS 信任该证书,因为它不是来自受信任的机构。

    通过覆盖 NSURLRequest.allowsAnyHTTPSCertificateForHost 的老派方法行不通。

    因为我使用的是 NSURLSession,所以你必须这样做:

    - (id) init {
        self = [super init];
        NSURLSessionConfiguration * config = [NSURLSessionConfiguration defaultSessionConfiguration];
        self.session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];
        return self;
    }
    
    - (void) URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler {
        completionHandler(NSURLSessionAuthChallengeUseCredential,[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
    }
    

    【讨论】:

    • 我们在哪里添加这个。我也在使用混合应用程序
    【解决方案2】:

    只需将 .cer 添加到 SecTrust

    func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Swift.Void) {
    
        if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {
            if let trust = challenge.protectionSpace.serverTrust,
               let pem = Bundle.main.path(forResource: "https", ofType: "cer"),
               let data = NSData(contentsOfFile: pem),
               let cert = SecCertificateCreateWithData(nil, data) {
                let certs = [cert]
                SecTrustSetAnchorCertificates(trust, certs as CFArray)
    
                completionHandler(URLSession.AuthChallengeDisposition.useCredential, URLCredential(trust: trust))
                return
            }
        }
    
        // Pinning failed
        completionHandler(URLSession.AuthChallengeDisposition.cancelAuthenticationChallenge, nil)
    }
    

    【讨论】:

      猜你喜欢
      • 2011-08-10
      • 1970-01-01
      • 2015-11-29
      • 2011-03-14
      • 2017-06-12
      • 2016-02-13
      • 2015-12-25
      • 1970-01-01
      • 2018-12-31
      相关资源
      最近更新 更多