XMPPFramework – 通过Openfire上的SSL连接

我试图通过SSL将我的用户从我的iOS XMPP聊天客户端连接到Openfire服务器。

在我的iOS客户端中:

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

在我的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]; } 

我尝试了这个线程的解决scheme: 与Openfire的XMPPFramework 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; } 

这一次,再次,不能连接到服务器,但没有提示错误。

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

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

我将不胜感激任何build议。

说明

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

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

这是因为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 */ 

请参阅XMPPFramework / GCDAsyncSocket.h & Deprecated Secure Transport Functions 。


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

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

  2. 在AppDelegate中定义variables

     BOOL customCertEvaluation; 
  3. 在setupStream中设置variables

     - (void)setupStream { ... customCertEvaluation = YES; } 
  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]; } 
  5. 手动validation对等

     /* * 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 } 

我在更新我的XMPPFramework后遇到同样的问题。 经过几天,试图找出哪里出了问题,我遇到了这个问题,但解决scheme没有为我工作。

这是为我工作。 这个问题似乎来自你的xmppStream.startTLSPolicy 。 设置startTLSPolicy显式为我工作。

 xmppStream.startTLSPolicy = XMPPStreamStartTLSPolicyPreferred; // or xmppStream.startTLSPolicy = XMPPStreamStartTLSPolicyRequired; 

这是一个为什么它的作品的解释。

在XMPPStream的handleStreamFeatures方法中,事实certificate。 如果您的XMPP服务器没有将“starttls”作为“required”返回,并且没有显式地设置startTLSPolicy(default = XMPPStreamStartTLSPolicyAllowed)。 客户端只会做一个正常的连接,而不是一个TLS的。

以下是在XMPPStream中执行检查的代码段(仅供参考)。

 /** * This method is called anytime we receive the server's stream features. * This method looks at the stream features, and handles any requirements so communication can continue. **/ - (void)handleStreamFeatures { NSAssert(dispatch_get_specific(xmppQueueTag), @"Invoked on incorrect queue"); XMPPLogTrace(); // Extract the stream features NSXMLElement *features = [rootElement elementForName:@"stream:features"]; // Check to see if TLS is required // Don't forget about that NSXMLElement bug you reported to apple (xmlns is required or element won't be found) NSXMLElement *f_starttls = [features elementForName:@"starttls" xmlns:@"urn:ietf:params:xml:ns:xmpp-tls"]; if (f_starttls) { if ([f_starttls elementForName:@"required"] || [self startTLSPolicy] >= XMPPStreamStartTLSPolicyPreferred) { // TLS is required for this connection // Update state state = STATE_XMPP_STARTTLS_1; // Send the startTLS XML request [self sendStartTLSRequest]; // We do not mark the stream as secure yet. // We're waiting to receive the <proceed/> response from the // server before we actually start the TLS handshake. // We're already listening for the response... return; } } else if (![self isSecure] && [self startTLSPolicy] == XMPPStreamStartTLSPolicyRequired) { // We must abort the connection as the server doesn't support our requirements. NSString *errMsg = @"The server does not support startTLS. And the startTLSPolicy is Required."; NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; otherError = [NSError errorWithDomain:XMPPStreamErrorDomain code:XMPPStreamUnsupportedAction userInfo:info]; // Close the TCP connection. [self disconnect]; // The socketDidDisconnect:withError: method will handle everything else return; } // Check to see if resource binding is required // Don't forget about that NSXMLElement bug you reported to apple (xmlns is required or element won't be found) NSXMLElement *f_bind = [features elementForName:@"bind" xmlns:@"urn:ietf:params:xml:ns:xmpp-bind"]; if (f_bind) { // Start the binding process [self startBinding]; // We're already listening for the response... return; } // It looks like all has gone well, and the connection should be ready to use now state = STATE_XMPP_CONNECTED; if (![self isAuthenticated]) { [self setupKeepAliveTimer]; // Notify delegates [multicastDelegate xmppStreamDidConnect:self]; } } 

您正尝试使用过时的API,请检查iPhoneXMPP示例以获取新的API – https://github.com/robbiehanson/XMPPFramework/commit/73f3c35a930b91d27e62bc19e91d9cdcc02c6e42

 customCertEvaluation = YES; allowSelfSignedCertificates = YES; allowSSLHostNameMismatch = NO; 

尝试这些可能会有所帮助