我正在使用CFStream/NSStream建立http连接。
我希望能够在三种情况下检测到SSL握手失败:

  • 情况A:服务器不受信任
  • 情况B:服务器是受信任的,但要求客户端证书
  • 案例C:服务器不受信任,并询问客户端证书

  • 今天,不对CFStream的SSL属性进行任何操作,我得到:
  • 情况A:错误-9807
  • 情况B:没有错误,但服务器拒绝连接(错误500)
  • 情况C:错误9807

  • 有没有一种方法可以配置CFStream以正确地区分这3种情况?还是在SSL握手期间进行一些回调?

    谢谢你的帮助。

    最佳答案

    前一段时间,我在使用SSL的CFSocket中遇到了同样的问题。 CFStream处理所有握手内容。我为NSStream编写了一个小类附加内容(基本代码来自Apple,不再有链接,如果找到它,我将其添加)。那对我有用。

    界面

    @interface NSStream (FSNetworkAdditions)
    
    + (void)qNetworkAdditions_getStreamsToHostNamed:(NSString *)hostName
                                               port:(NSInteger)port
                                        inputStream:(out NSInputStream **)inputStreamPtr
                                       outputStream:(out NSOutputStream **)outputStreamPtr;
    
    @end
    

    与实现
    #import "FSNetworkAdditions.h"
    
    @implementation NSStream (FSNetworkAdditions)
    
    + (void)qNetworkAdditions_getStreamsToHostNamed:(NSString *)hostName
                                               port:(NSInteger)port
                                        inputStream:(out NSInputStream **)inputStreamPtr
                                       outputStream:(out NSOutputStream **)outputStreamPtr
    {
        CFReadStreamRef     readStream;
        CFWriteStreamRef    writeStream;
    
        assert(hostName != nil);
        assert( (port > 0) && (port < 65536) );
        assert( (inputStreamPtr != NULL) || (outputStreamPtr != NULL) );
    
        readStream = NULL;
        writeStream = NULL;
    
        CFStreamCreatePairWithSocketToHost(
                                           NULL,
                                           (CFStringRef) hostName,
                                           port,
                                           ((inputStreamPtr  != NULL) ? &readStream : NULL),
                                           ((outputStreamPtr != NULL) ? &writeStream : NULL)
                                           );
    
        NSDictionary *settings = [[NSDictionary alloc] initWithObjectsAndKeys:
                                  [NSNumber numberWithBool:YES], kCFStreamSSLAllowsExpiredCertificates,
                                  [NSNumber numberWithBool:YES], kCFStreamSSLAllowsAnyRoot,
                                  [NSNumber numberWithBool:YES], kCFStreamSSLAllowsExpiredRoots,
                                  [NSNumber numberWithBool:NO], kCFStreamSSLValidatesCertificateChain,
                                  //kCFNull,kCFStreamSSLPeerName,
                                  kCFStreamSocketSecurityLevelSSLv3, kCFStreamSSLLevel,
                                  [NSNumber numberWithBool:YES], kCFStreamPropertyShouldCloseNativeSocket,
                                  nil];
    
        if (readStream) {
            CFReadStreamSetProperty(readStream, kCFStreamPropertySSLSettings, (CFTypeRef)settings);
        }
    
        if (writeStream) {
            CFWriteStreamSetProperty(writeStream, kCFStreamPropertySSLSettings, (CFTypeRef)settings);
        }
    
        if (inputStreamPtr != NULL) {
            *inputStreamPtr  = CFBridgingRelease(readStream);
        }
        if (outputStreamPtr != NULL) {
            *outputStreamPtr = CFBridgingRelease(writeStream);
        }
    
    
    }
    
    @end
    

    就是这样,现在您可以像这样连接到服务器:
    NSInputStream   *inputStream;
    NSOutputStream  *outputStream;
    [NSStream qNetworkAdditions_getStreamsToHostNamed:host
                                                 port:port
                                          inputStream:&inputStream
                                         outputStream:&outputStream];
    
            inputStream.delegate  = self;
            outputStream.delegate = self;
    

    其中“自我”符合NSStreamDelegate协议(protocol)。

    希望这些摘要对您有所帮助。

    关于objective-c - 如何为SSL握手配置CFStream(或NSStream)?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13534091/

    10-12 03:04