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];`
这是因为kCFStreamSSLAllowsAnyRoot
& SSLSetAllowsAnyRoot
已被弃用。
/* * ==== 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 。
解
-
转到Openfire服务器>安全设置>客户端连接安全性
Check: Required - Clients can only connect to the server using secured connections.
-
在AppDelegate中定义variables
BOOL customCertEvaluation;
-
在setupStream中设置variables
- (void)setupStream { ... customCertEvaluation = YES; }
-
在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]; }
-
手动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;
尝试这些可能会有所帮助