ios xcode9.0 swift4.0 MQTT - 如何使用证书连接到MQTT服务器?

时间:2018-01-25 11:09:21

标签: ios swift xcode certificate mqtt

这是我想在iPhone应用程序中执行的任务:

  1. 下载&从test.mosquitto.org安装证书“mosquitto.org.crt”

  2. 在8883端口连接到mqtt服务器“test.mosquitto.org”

  3. 希望在调试消息中看到“连接成功”
  4. 退出应用,删除iphone中的证书
  5. 回到应用程序&重试再次连接到8883端口的mqtt服务器
  6. 预计会看到:连接失败
  7. 我尝试过CocoaMQTT: https://github.com/emqtt/CocoaMQTT 但即使证书已被删除,CocoaMQTT仍然可以成功连接到服务器。

    以下是我从cocoaMQTT示例修改的代码:

    import UIKit
    import CocoaMQTT
    
    class ViewController: UIViewController {
        var mqtt: CocoaMQTT?
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            mqttSetting()
        }
    
    
    
        func mqttSetting() {
            let clientID: String = "testID123456789"
            let mqttServer: String = "test.mosquitto.org"
            let mqttPort: UInt16 = 8883
            let useSSL: Bool = true
    
            mqtt = CocoaMQTT(clientID: clientID, host: mqttServer, port: mqttPort)
            mqtt!.username = nil
            mqtt!.password = nil
            mqtt!.keepAlive = 60
            mqtt!.delegate = self
    
            if useSSL == true{
                mqtt!.enableSSL = true
                mqtt!.allowUntrustCACertificate = true
            }
    
            mqtt!.connect()
        }
    
    }
    
    extension ViewController: CocoaMQTTDelegate {
        // Optional ssl CocoaMQTTDelegate
        func mqtt(_ mqtt: CocoaMQTT, didReceive trust: SecTrust, completionHandler: @escaping (Bool) -> Void) {
            TRACE("trust: \(trust)")
            /// Validate the server certificate
            ///
            /// Some custom validation...
            ///
            /// if validatePassed {
            ///     completionHandler(true)
            /// } else {
            ///     completionHandler(false)
            /// }
            completionHandler(true)
        }
    
        func mqtt(_ mqtt: CocoaMQTT, didConnectAck ack: CocoaMQTTConnAck) {
            TRACE("ack: \(ack)")
    
            if ack == .accept {
                mqtt.subscribe("chat/room/animals/client/+", qos: CocoaMQTTQOS.qos1)
    
    
            }
        }
    
        func mqtt(_ mqtt: CocoaMQTT, didStateChangeTo state: CocoaMQTTConnState) {
            TRACE("new state: \(state)")
        }
    
        func mqtt(_ mqtt: CocoaMQTT, didPublishMessage message: CocoaMQTTMessage, id: UInt16) {
            TRACE("message: \(String(describing: message.string?.description)), id: \(id)")
        }
    
        func mqtt(_ mqtt: CocoaMQTT, didPublishAck id: UInt16) {
            TRACE("id: \(id)")
        }
    
        func mqtt(_ mqtt: CocoaMQTT, didReceiveMessage message: CocoaMQTTMessage, id: UInt16 ) {
            TRACE("message: \(String(describing: message.string?.description)), id: \(id)")
    
        }
    
        func mqtt(_ mqtt: CocoaMQTT, didSubscribeTopic topic: String) {
            TRACE("topic: \(topic)")
        }
    
        func mqtt(_ mqtt: CocoaMQTT, didUnsubscribeTopic topic: String) {
            TRACE("topic: \(topic)")
        }
    
        func mqttDidPing(_ mqtt: CocoaMQTT) {
            TRACE()
        }
    
        func mqttDidReceivePong(_ mqtt: CocoaMQTT) {
            TRACE()
        }
    
        func mqttDidDisconnect(_ mqtt: CocoaMQTT, withError err: Error?) {
            TRACE("\(err.debugDescription)")
        }
    }
    
    extension ViewController {
        func TRACE(_ message: String = "", fun: String = #function) {
            let names = fun.components(separatedBy: ":")
            var prettyName: String
            if names.count == 1 {
                prettyName = names[0]
            } else {
                prettyName = names[1]
            }
    
            if fun == "mqttDidDisconnect(_:withError:)" {
                prettyName = "didDisconect"
            }
    
            print("[TRACE] [\(prettyName)]: \(message)")
        }
    }
    

    上面的代码在调试窗口中给出了以下结果(我已经在我的iPhone中删除了test.mosquitto.org的证书):

    [TRACE] [didStateChangeTo]: new state: connecting
    [TRACE] [didReceive]: trust: <SecTrustRef: 0x170129420>
    [TRACE] [didStateChangeTo]: new state: connected
    [TRACE] [didConnectAck]: ack: accept
    [TRACE] [didSubscribeTopic]: topic: chat/room/animals/client/+
    [TRACE] [mqttDidPing]: 
    [TRACE] [mqttDidReceivePong]: 
    [TRACE] [mqttDidPing]: 
    [TRACE] [mqttDidReceivePong]: 
    

    我预计与mqtt服务器的连接不应该成功,因为我已经删除了iPhone中的证书。但是,连接仍然成功,这不是我预期的结果。知道该怎么办?

1 个答案:

答案 0 :(得分:0)

您的服务器可能使用单向认证。

您可以使用单向认证:

mqtt!.enableSSL = true

本地不需要证书。

如果要信任所有不信任的CA证书,可以执行以下操作:

mqtt.allowUntrustCACert = true

(p12用于2通认证)