XMPPFramework - 在Openfire上通过SSL连接

Kei*_*OYS 5 ssl xmpp openfire ios xmppframework

我正在尝试通过SSL将我的用户从我的iOS XMPP聊天客户端连接到Openfire服务器.

在我的iOS客户端中:

- (void)setupStream 
{
    ...
    // BOOL values for security settings
    customCertEvaluation = NO;
    allowSelfSignedCertificates = YES;
    allowSSLHostNameMismatch = NO;
}
Run Code Online (Sandbox Code Playgroud)

在我的Openfire服务器的安全设置 > 客户端连接安全性中,我设置了:

Required - Clients can only connect to the server using secured connections.

因此,将调用以下委托方法:

- (void)xmppStream:(XMPPStream *)sender willSecureWithSettings:(NSMutableDictionary *)settings 
{
    NSString *expectedCertName = [xmppStream.myJID domain];

    if (customCertEvaluation)
        [settings setObject:@(YES) forKey:GCDAsyncSocketManuallyEvaluateTrust];

    if (allowSelfSignedCertificates)
        [settings setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCFStreamSSLAllowsAnyRoot];

    if (allowSSLHostNameMismatch)
        [settings setObject:[NSNull null] forKey:(NSString *)kCFStreamSSLPeerName];

    else
        if (expectedCertName)
            [settings setObject:expectedCertName forKey:(NSString *)kCFStreamSSLPeerName];
}
Run Code Online (Sandbox Code Playgroud)

我从这个线程尝试了这个解决方案:XMPPFramework与Openfire的TLS/SSL连接

但是,当我运行我的应用程序并尝试连接到服务器时,我会收到此错误:

Security option unavailable - kCFStreamSSLAllowsAnyRoot - You must use manual trust evaluation

我仔细研究了这个GCDAsyncSocket课程,并意识到kCFStreamSSLAllowsAnyRoot它已被声明为已弃用.实施NSAssert以故意抛出错误.

接下来,我决定改变我的BOOL值:

- (void)setupStream 
{
    ...
    // BOOL values for security settings
    // Manually evaluate trust
    customCertEvaluation = YES;
    allowSelfSignedCertificates = NO;
    allowSSLHostNameMismatch = NO;
}
Run Code Online (Sandbox Code Playgroud)

这次,再次,没有连接到服务器,但没有提示错误.

如果我将客户端连接安全性更改回原始设置> 可选,我可以很好地连接到Openfire .但是,我不会通过SSL连接,如每个用户在客户端会话中的状态旁边的锁定图标所示.

我的Android客户端(使用Smack API for XMPP)通过SSL连接到Openfire而没有任何问题.所以我想知道是否有必要使用XMPPFramework为我的iOS客户端实现的解决方法.

我非常感谢任何建议.

Kei*_*OYS 8

说明

在最新版本的XMPP(4月22日之后)中,您不能使用allowSelfSignedCertificates = YES以下内容:

if (allowSelfSignedCertificates)
    [settings setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCFStreamSSLAllowsAnyRoot];`
Run Code Online (Sandbox Code Playgroud)

这是因为,kCFStreamSSLAllowsAnyRootSSLSetAllowsAnyRoot已被弃用.

 /* 
  * ==== The following UNAVAILABLE KEYS are: (with throw an exception)
  * - kCFStreamSSLAllowsAnyRoot (UNAVAILABLE)
  *     You MUST use manual trust evaluation instead (see GCDAsyncSocketManuallyEvaluateTrust).
  *     Corresponding deprecated method: SSLSetAllowsAnyRoot
  */
Run Code Online (Sandbox Code Playgroud)

请参阅XMPPFramework/GCDAsyncSocket.h不推荐的安全传输功能.


  1. 转到Openfire服务器>安全设置>客户端连接安全性

    Check: Required - Clients can only connect to the server using secured connections.

  2. 在AppDelegate中定义变量

    BOOL customCertEvaluation;
    
    Run Code Online (Sandbox Code Playgroud)
  3. 在setupStream中设置变量

    - (void)setupStream 
    {
        ...
        customCertEvaluation = YES;
    }
    
    Run Code Online (Sandbox Code Playgroud)
  4. 在willSecureWithSettings中设置安全设置

    - (void)xmppStream:(XMPPStream *)sender willSecureWithSettings:(NSMutableDictionary *)settings
    {
        /*
         * Properly secure your connection by setting kCFStreamSSLPeerName 
         * to your server domain name
         */
        [settings setObject:xmppStream.myJID.domain forKey:(NSString *)kCFStreamSSLPeerName];
    
        /*
         * Use manual trust evaluation
         * as stated in the XMPPFramework/GCDAsyncSocket code documentation
         */
        if (customCertEvaluation)
            [settings setObject:@(YES) forKey:GCDAsyncSocketManuallyEvaluateTrust];
    }
    
    Run Code Online (Sandbox Code Playgroud)
  5. 手动验证对等体

    /*
     * This is only called if the stream is secured with settings that include:
     * - GCDAsyncSocketManuallyEvaluateTrust == YES
     * That is, if a delegate implements xmppStream:willSecureWithSettings:, and plugs in that key/value pair.
     */
     - (void)xmppStream:(XMPPStream *)sender didReceiveTrust:(SecTrustRef)trust completionHandler:(void (^)(BOOL shouldTrustPeer))completionHandler
     {
         /* Custom validation for your certificate on server should be performed */
    
         completionHandler(YES); // After this line, SSL connection will be established
     }
    
    Run Code Online (Sandbox Code Playgroud)