iOS開發(fā)中MQTTKit的TLS/SSL支持方案

MQTTKit是一個基于Mosquitto庫實現(xiàn)的MQTT協(xié)議網(wǎng)絡(luò)庫,但是已經(jīng)停止更新很久了。日常開發(fā)的功能基本實現(xiàn),但一直未支持TLS/SSL。最近我fork了這個項目并進(jìn)行了修改,截止2017.5.23主要做了以下修改

  • 更新Mosquitto庫
  • 完成了on_log的回調(diào),可以查看Mosquitto內(nèi)部的打印幫助調(diào)試
  • 增添了TLS/SSL的支持
  • 細(xì)節(jié)的完善
    ...

后續(xù)我會檢查原項目里未解決的issus,并將Mosquitto庫已經(jīng)支持的功能同步過來。項目地址MQTTKit。如果項目需要支持TLS/SSL,你無法直接導(dǎo)入三方框架直接使用,需要進(jìn)行一些配置。這篇文章會介紹如何讓MQTTKit在你的項目中支持TLS/SSL。并給出各種情況下的示例代碼。

libmosquitto文件夾和MQTTKit文件導(dǎo)入項目,并設(shè)置全局宏WITH_TLS=1

WITH_TLS

這個時候你編譯程序,會發(fā)現(xiàn)在mosquitto_internal.h文件里報錯file <openssl.h> not founded。原因在這里官方文檔。Apple認(rèn)為雖然Openssl是一個應(yīng)用非常廣泛的開源庫,但是版本更替其中的API一直變更無法穩(wěn)定。出于這個原因,Openssl不再作為iOS的一部分,即使OS X仍然提供Openssl,但已經(jīng)廢棄了Openssl開源庫。在應(yīng)用開發(fā)中是非常不鼓勵開發(fā)者使用Openssl庫。
但是如果我們確實要用的話,應(yīng)該自己編譯OpenSSL代碼,然后靜態(tài)鏈接。具體的操作如下:

  • OpenSSL-for-iPhone打包下載源碼,解壓到桌面。cd進(jìn)入目錄下執(zhí)行./build-libssl.sh。執(zhí)行完成以后目錄下多了兩個文件夾。
編譯
  • 將圖中標(biāo)注的兩個文件夾拖入工程。其中include包含的是頭文件,lib包含的是library。
導(dǎo)入工程
  • 加入工程之后我們需要在Build Setting中進(jìn)行設(shè)置,在Header Search Paths中添加include文件夾的路徑
    Header Search Paths

Library Search Paths中檢查是否有lib路徑

Library Search Paths

至此,項目可以完整的運(yùn)行起來。Mosquitto提供了測試的地址。端口1883是普通的服務(wù),無需用戶名密碼即可連接。以下提供了一個簡單的連接測試代碼。

- (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是單向驗證的接口,你需要驗證服務(wù)器的連接,驗證證書的下載地址。測試代碼如下。我已經(jīng)提前下好證書改名server.crt導(dǎo)入工程。

- (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需要雙向驗證,客戶端也需要向服務(wù)器提供證書。這個比較麻煩的是需要我們自己生成私鑰和證書,我之前操作的時候遇見了一些麻煩,會在另一篇文章詳細(xì)介紹。這里提供一段測試代碼,其中client.keyclient.crt是我已經(jīng)生成的客戶端私鑰和證書

- (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);
        }
    }];
}

后續(xù)我會持續(xù)維護(hù)MQTTKit,如果在使用過程中仍有疑問,或者發(fā)現(xiàn)了任何bug,歡迎在Github和簡書上一起討論解決。

如果對你有所幫助,希望給我一個Star :)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容