无法从iOS访问https服务

前端之家收集整理的这篇文章主要介绍了无法从iOS访问https服务前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在尝试访问https协议可用的Web服务.最初我得到以下错误

NSURLSession/NSURLConnection HTTP load Failed (kcfStreamErrorDomainSSL,-9802)
errorAn SSL error has occurred and a secure connection to the server cannot be made.@H_502_5@

我通过在我的info.plist中添加以下内容来修复它:@H_502_5@

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
    <key>NSExceptionDomains</key>
    <dict>
        <key>xx.xx.xxx.xxx</key>
        <dict>
            <key>NSExceptionAllowsInsecureHTTPLoads</key>
            <true/>
            <key>NSIncludesSubdomains</key>
            <true/>
            <key>NSThirdPartyExceptionAllowsInsecureHTTPLoads</key>
            <true/>
        </dict>
    </dict>
</dict>

但是现在我正在连接到DIDFinishLoading代理方法中作为html响应:@H_502_5@

400错误请求@H_502_5@

错误的请求@H_502_5@

您的浏览器发送了此服务器无法理解的请求.@H_502_5@

我正在使用以下设置与服务器的信任:@H_502_5@

func connection(connection: NSURLConnection,canAuthenticateAgainstProtectionSpace protectionSpace: NSURLProtectionSpace) -> Bool{
    return true
}
func connection(connection: NSURLConnection,willSendRequestForAuthenticationChallenge challenge: NSURLAuthenticationChallenge){
    print("willSendRequestForAuthenticationChallenge")

    let protectionSpace:NSURLProtectionSpace = challenge.protectionSpace
    let sender: NSURLAuthenticationChallengeSender? = challenge.sender

    if(protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust){
        let trust:SecTrustRef = challenge.protectionSpace.serverTrust!
        let credential:NSURLCredential = NSURLCredential.init(forTrust: trust)
        sender?.useCredential(credential,forAuthenticationChallenge: challenge)
    }
    else{
        sender?.performDefaultHandlingForAuthenticationChallenge!(challenge)
    }
}

有人可以帮我找出问题吗?@H_502_5@

UPDATE1:
服务器日志显示以下错误:@H_502_5@

Hostname xx.xx.xxx.xx provided via SNI and hostname my_secured_host_name provided via HTTP are different@H_502_5@

如何在SNI中添加主机名?@H_502_5@

UPDATE2:
由于服务已经是https,所以我已经从info.plist中删除了通过http的密钥@H_502_5@

UPDATE3:
当我尝试使用openssl as@H_502_5@

openssl s_client -showcerts -connect xx.xx.xxx.xxx:443@H_502_5@

但我得到以下错误:@H_502_5@

CONNECTED(00000003) 8012:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:/SourceCache/OpenSSL098/OpenSSL098-52.40.1/src/ssl/s23_lib.c:185@H_502_5@

UPDATE4:
更改了Info.plist以执行以下操作:@H_502_5@

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>xx.xx.xxx.xxx</key>
        <dict>
            <key>NSExceptionRequiresForwardSecrecy</key>
            <false/>
            <key>NSIncludesSubdomains</key>
            <true/>
        </dict>
    </dict>
</dict>

仍然收到以下错误:@H_502_5@

NSURLSession/NSURLConnection HTTP load Failed (kcfStreamErrorDomainSSL,-9802)
errorAn SSL error has occurred and a secure connection to the server cannot be made.@H_502_5@

问候
潘卡@H_502_5@

解决方法

在其他答案和评论中已经解决的ATS问题之上,您似乎试图通过其IP地址连接到SSL服务器.
以下参考可能是有用的(我从苹果的iOS开发库中逐字引用):

To override the hostname (to allow a certificate for one specific site
to work for another specific site,or to allow a certificate to work
when you connected to a host by its IP address
),you must replace
the policy object that the trust policy uses to determine how to
interpret the certificate. To do this,first create a new TLS policy
object for the desired hostname. Then create an array containing that
policy. Finally,tell the trust object to use that array for future
evaluation of trust.@H_502_5@

SecTrustRef changeHostForTrust(SecTrustRef trust)
{
        CFMutableArrayRef newTrustPolicies = CFArrayCreateMutable(
                kcfAllocatorDefault,&kcfTypeArrayCallBacks);

        SecPolicyRef sslPolicy = SecPolicyCreateSSL(true,CFSTR("www.example.com"));

        CFArrayAppendValue(newTrustPolicies,sslPolicy);

#ifdef MAC_BACKWARDS_COMPATIBILITY
        /* This technique works in OS X (v10.5 and later) */

        SecTrustSetPolicies(trust,newTrustPolicies);
        CFRelease(oldTrustPolicies);

        return trust;
#else
        /* This technique works in iOS 2 and later,or
           OS X v10.7 and later */

        CFMutableArrayRef certificates = CFArrayCreateMutable(
                kcfAllocatorDefault,&kcfTypeArrayCallBacks);

        /* Copy the certificates from the original trust object */
        CFIndex count = SecTrustGetCertificateCount(trust);
        CFIndex i=0;
        for (i = 0; i < count; i++) {
                SecCertificateRef item = SecTrustGetCertificateAtIndex(trust,i);
                CFArrayAppendValue(certificates,item);
        }

        /* Create a new trust object */
        SecTrustRef newtrust = NULL;
        if (SecTrustCreateWithCertificates(certificates,newTrustPolicies,&newtrust) != errSecSuccess) {
                /* Probably a good spot to log something. */

                return NULL;
        }

        return newtrust;
#endif
}

资料来源:iOS Developer Library — Overriding TLS Chain Validation Correctly — Manipulating Trust Objects@H_502_5@

请注意,在同一页面上,您可以找到处理自签名SSL证书的其他代码段,以防您处理此类证书.@H_502_5@

要在Swift项目中使用此功能,请将新的C文件添加到您的项目(File .. New .. File .. iOS / Source / C_File),例如mysectrust.c和相应的头mysectrust.h(如果XCode要求你创建一个桥接头,说是)@H_502_5@

mysectrust.h@H_502_5@

#ifndef mysectrust_h
#define mysectrust_h

#include <Security/Security.h>

SecTrustRef changeHostForTrust(SecTrustRef trust);

#endif /* mysectrust_h */

mysectrust.c@H_502_5@

#include "mysectrust.h"

SecTrustRef changeHostForTrust(SecTrustRef trust)
{
    CFMutableArrayRef newTrustPolicies = CFArrayCreateMutable(
                                                              kcfAllocatorDefault,&kcfTypeArrayCallBacks);

    SecPolicyRef sslPolicy = SecPolicyCreateSSL(true,CFSTR("www.example.com"));

    CFArrayAppendValue(newTrustPolicies,sslPolicy);

#ifdef MAC_BACKWARDS_COMPATIBILITY
    /* This technique works in OS X (v10.5 and later) */

    SecTrustSetPolicies(trust,newTrustPolicies);
    CFRelease(oldTrustPolicies);

    return trust;
#else
    /* This technique works in iOS 2 and later,or
     OS X v10.7 and later */

    CFMutableArrayRef certificates = CFArrayCreateMutable(
                                                          kcfAllocatorDefault,&kcfTypeArrayCallBacks);

    /* Copy the certificates from the original trust object */
    CFIndex count = SecTrustGetCertificateCount(trust);
    CFIndex i=0;
    for (i = 0; i < count; i++) {
        SecCertificateRef item = SecTrustGetCertificateAtIndex(trust,i);
        CFArrayAppendValue(certificates,item);
    }

    /* Create a new trust object */
    SecTrustRef newtrust = NULL;
    if (SecTrustCreateWithCertificates(certificates,&newtrust) != errSecSuccess) {
        /* Probably a good spot to log something. */

        return NULL;
    }

    return newtrust;
#endif
}

当然,请使用您的主机名替换上述代码中的www.example.com.@H_502_5@

然后,在Xcode项目projectname-Bridging-Header.h中找到桥接头,并附加以下行:@H_502_5@

#import "mysectrust.h"

现在你可以从Swift调用这个函数,例如:@H_502_5@

func whatever(trust: SecTrustRef){

    let newTrust = changeHostForTrust(trust) // call to C function
    ...
}

猜你在找的iOS相关文章