美文网首页网络协议@IT·互联网iOS Developer
iOS开发中MQTTKit的TLS/SSL支持方案

iOS开发中MQTTKit的TLS/SSL支持方案

作者: Noskthing | 来源:发表于2017-05-23 20:36 被阅读862次

    MQTTKit是一个基于Mosquitto库实现的MQTT协议网络库,但是已经停止更新很久了。日常开发的功能基本实现,但一直未支持TLS/SSL。最近我fork了这个项目并进行了修改,截止2017.5.23主要做了以下修改

    • 更新Mosquitto库
    • 完成了on_log的回调,可以查看Mosquitto内部的打印帮助调试
    • 增添了TLS/SSL的支持
    • 细节的完善
      ...

    后续我会检查原项目里未解决的issus,并将Mosquitto库已经支持的功能同步过来。项目地址MQTTKit。如果项目需要支持TLS/SSL,你无法直接导入三方框架直接使用,需要进行一些配置。这篇文章会介绍如何让MQTTKit在你的项目中支持TLS/SSL。并给出各种情况下的示例代码。

    libmosquitto文件夹和MQTTKit文件导入项目,并设置全局宏WITH_TLS=1

    WITH_TLS
    这个时候你编译程序,会发现在mosquitto_internal.h文件里报错file <openssl.h> not founded。原因在这里官方文档。Apple认为虽然Openssl是一个应用非常广泛的开源库,但是版本更替其中的API一直变更无法稳定。出于这个原因,Openssl不再作为iOS的一部分,即使OS X仍然提供Openssl,但已经废弃了Openssl开源库。在应用开发中是非常不鼓励开发者使用Openssl库。
    但是如果我们确实要用的话,应该自己编译OpenSSL代码,然后静态链接。具体的操作如下:
    • OpenSSL-for-iPhone打包下载源码,解压到桌面。cd进入目录下执行./build-libssl.sh。执行完成以后目录下多了两个文件夹。
    编译
    • 将图中标注的两个文件夹拖入工程。其中include包含的是头文件,lib包含的是library。
    导入工程
    • 加入工程之后我们需要在Build Setting中进行设置,在Header Search Paths中添加include文件夹的路径
      Header Search Paths

    Library Search Paths中检查是否有lib路径

    Library Search Paths

    至此,项目可以完整的运行起来。Mosquitto提供了测试的地址。端口1883是普通的服务,无需用户名密码即可连接。以下提供了一个简单的连接测试代码。

    - (void)testConnect
    {
        client = [[MQTTClient alloc] initWithClientId:[NSString stringWithFormat:@"MQTTKitTests-%@", [[NSUUID UUID] UUIDString]]];
        
        client.host = @"test.mosquitto.org";
        client.port = 1883;
        
        [client connectWithCompletionHandler:^(MQTTConnectionReturnCode code) {
            if (code == 0)
            {
                NSLog(@"Connect Success");
            }
            else
            {
                NSLog(@"Connect Fail! State Code is %lu", (unsigned long)code);
            }
        }];
    }
    

    端口8883是单向验证的接口,你需要验证服务器的连接,验证证书的下载地址。测试代码如下。我已经提前下好证书改名server.crt导入工程。

    - (void)testTLSWithOneWayAuthentication
    {
        client = [[MQTTClient alloc] initWithClientId:[NSString stringWithFormat:@"MQTTKitTests-%@", [[NSUUID UUID] UUIDString]]];
        
        client.host = @"test.mosquitto.org";
        client.port = 8883;
        
        client.tlsCafile = [[NSBundle mainBundle] pathForResource:@"server" ofType:@"crt"];
        
        [client connectWithCompletionHandler:^(MQTTConnectionReturnCode code) {
            if (code == 0)
            {
                NSLog(@"Connect Success");
            }
            else
            {
                NSLog(@"Connect Fail! State Code is %lu", (unsigned long)code);
            }
        }];
    }
    

    端口8884需要双向验证,客户端也需要向服务器提供证书。这个比较麻烦的是需要我们自己生成私钥和证书,我之前操作的时候遇见了一些麻烦,会在另一篇文章详细介绍。这里提供一段测试代码,其中client.keyclient.crt是我已经生成的客户端私钥和证书

    - (void)testTLSWithTwoWayAuthentication
    {
        client = [[MQTTClient alloc] initWithClientId:[NSString stringWithFormat:@"MQTTKitTests-%@", [[NSUUID UUID] UUIDString]]];
        
        client.host = @"test.mosquitto.org";
        client.port = 8884;
        
        client.tlsCerPath = [[NSBundle mainBundle] pathForResource:@"client" ofType:@"crt"];
        client.tlsCerKeyPath = [[NSBundle mainBundle] pathForResource:@"client" ofType:@"key"];
        client.tlsCafile = [[NSBundle mainBundle] pathForResource:@"server" ofType:@"crt"];
        client.tlsPeerCertVerify = YES;
        
        [client connectWithCompletionHandler:^(MQTTConnectionReturnCode code) {
            if (code == 0)
            {
                NSLog(@"Connect Success");
            }
            else
            {
                NSLog(@"Connect Fail! State Code is %lu", (unsigned long)code);
            }
        }];
    }
    

    后续我会持续维护MQTTKit,如果在使用过程中仍有疑问,或者发现了任何bug,欢迎在Github和简书上一起讨论解决。

    如果对你有所帮助,希望给我一个Star :)

    相关文章

      网友评论

      • iOS104:为啥不用MQTTClient,这个三方库支持SSL,还有人一直在维护
      • wellcoding:'tls_mosq.h' file not found with <angled> include; use "quotes" instead 加完include 和lib框架的路径报这样的错
        wellcoding:但是文件是存在的,不知道是哪里的依赖问题吗
      • 6f22a89666ff:你好博主 MQTT 带TLS验证 用的mosquitto 在mosquitto的连接成功回调中调用订阅和取消订阅 是可以的 但是当连接完成后 点击按钮去调用经常就会报错MOSQ_ERR_ERRNO: Protocol error 请问有知道是什么情况的吗?谢谢
      • a558d5f37b23:这个库好像不怎么稳定
      • e0ce849b8eb3:你好,我想问下为什么我在preprocessor macro下加了WITH_TLS=1之后项目基本上就可以编译了。可是这个时候我根本就还没有加 OpenSSL的库。虽然如此但是我还是引入了OpenSSL。但是问题在于我运行的时候,居然在 setTlsCaFile 这里报 unrecognized selector sent to instance。我觉得特别奇怪。编译的时候也没说找不到这个方法,但是编译后调用这个方法又找不到。请问你知道这个是什么导致的吗?然后就是你说的没有OpenSSL编译会报错,可是我没引入他也没报错。这个让我很郁闷。。。
        e0ce849b8eb3:@Noskthing 你好,谢谢你。我发现是我编译搞错了。我只在App工程里加了WITH_TLS=1。原来编译 MQTTKit之前就需要加了。然后我的OpenSSL是直接加到App工程里的,难怪这样没出问题。
        Noskthing:@田俊麟 我觉得你还是要检查一下宏的定义。因为openssl的头文件只有在WITH_TLS打开的情况下才会导入,如果编译成功说明导入openssl的地方WITH_TLS=0。同理未找到的selector也是在WITH_TLS打开的情况下定义的变量tlsCaFile的set方法
      • Try_fly:博主问一下,我这边用SSL连接成功,但是订阅主题和发送消息没有消息返回是什么问题?
        Try_fly:@Try_fly 博主了解过现在的MQTTClient是否支持SSL/TLS?我看代码里好像有TLS但是他要求上传的证书为.p12。
        Try_fly:已成功拿回数据,原来是pub的时候子节点搞错了
        Noskthing:@Try_fly 你确定链接成功了吗?PINGRESQ和PINHRESP正常收发吗?订阅主题收到ack了吗?你按照这个顺序排查一下吧。ping的默认间隔是60
        s

      本文标题:iOS开发中MQTTKit的TLS/SSL支持方案

      本文链接:https://www.haomeiwen.com/subject/ihpgxxtx.html