You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在C/C++中使用libmosquitto配置MQTT用户名密码连接的方法

问题:libmosquitto客户端实现用户名密码认证的正确方式

我在Ubuntu下用C/C++开发MQTT客户端,采用libmosquitto库。之前注意到mosquitto_new()的第三个void指针参数在无用户名密码的示例中都设为NULL,误以为要启用认证就得修改这个参数,但硬编码账号密码存在安全隐患。我知道Mosquitto Broker可通过配置文件禁用匿名访问并指定账号密码文件,但不清楚客户端代码里该怎么正确实现认证,现寻求正确方法。

我当前能正常运行的发布者代码如下:

#include <iostream>
#include <stdio.h>
#include </home/dave/mosquitto/include/mosquitto.h>

using namespace std;

int main(){
    int rc;
    char message[] = "Hello World testing";
    
    struct mosquitto * mosq;

    mosquitto_lib_init();
    

    mosq = mosquitto_new("publisher-test", true, NULL);

    rc = mosquitto_connect(mosq, "130.246.57.26", 1883, 60); // ip 130.246.57.26
    if(rc != 0){
        printf("Client could not connect to broker! Error Code: %d\n", rc);
        mosquitto_destroy(mosq);
        return -1;
    }
    printf("We are now connected to the broker!\n");

    mosquitto_publish(mosq, NULL, "test/1", sizeof(message), &message , 0, false);

    mosquitto_disconnect(mosq);
    mosquitto_destroy(mosq);

    mosquitto_lib_cleanup();
    return 0;
}

解答

1. 澄清mosquitto_new()第三个参数的作用

这个参数是用户自定义数据指针,和认证完全无关。它的作用是让你在MQTT回调函数(如连接回调、消息回调)中获取自定义上下文数据(比如结构体、类实例指针),和用户名密码认证没有任何关联,继续设为NULL即可。

2. 正确的认证实现:使用mosquitto_username_pw_set()

要给客户端设置用户名密码,只需在mosquitto_connect()之前调用mosquitto_username_pw_set()函数,函数原型:

int mosquitto_username_pw_set(struct mosquitto *mosq, const char *username, const char *password);
  • username:要设置的用户名字符串指针,传NULL可清空已设置的用户名
  • password:对应的密码字符串指针,传NULL则仅设置用户名(部分Broker支持无密码的用户名认证)

3. 避免硬编码账号密码的安全方案

不要把账号密码直接写在代码里,推荐以下几种安全获取方式:

  • 从环境变量读取:终端先执行export MQTT_USER="your_username"、export MQTT_PASS="your_password",代码中用getenv()获取
  • 从本地配置文件读取:读取权限设为600的配置文件,仅允许当前用户访问
  • 从命令行参数传入:启动程序时通过参数指定,比如./mqtt_pub -u your_username -p your_password

修改后的示例代码(以环境变量读取为例)

#include <iostream>
#include <stdio.h>
#include <stdlib.h> // 用于getenv函数
#include </home/dave/mosquitto/include/mosquitto.h>

using namespace std;

int main(){
    int rc;
    char message[] = "Hello World testing";
    
    struct mosquitto * mosq;

    mosquitto_lib_init();
    
    // 创建客户端实例,第三个参数保持NULL
    mosq = mosquitto_new("publisher-test", true, NULL);
    if(!mosq){
        fprintf(stderr, "Failed to create mosquitto instance\n");
        return -1;
    }

    // 从环境变量读取用户名密码
    const char* mqtt_user = getenv("MQTT_USER");
    const char* mqtt_pass = getenv("MQTT_PASS");
    if(mqtt_user && mqtt_pass){
        rc = mosquitto_username_pw_set(mosq, mqtt_user, mqtt_pass);
        if(rc != 0){
            fprintf(stderr, "Failed to set username/password: Error Code %d\n", rc);
            mosquitto_destroy(mosq);
            return -1;
        }
    } else {
        fprintf(stderr, "MQTT_USER or MQTT_PASS environment variable not set\n");
        mosquitto_destroy(mosq);
        return -1;
    }

    // 连接Broker
    rc = mosquitto_connect(mosq, "130.246.57.26", 1883, 60);
    if(rc != 0){
        printf("Client could not connect to broker! Error Code: %d\n", rc);
        mosquitto_destroy(mosq);
        return -1;
    }
    printf("We are now connected to the broker!\n");

    // 发布消息:注意sizeof(message)包含末尾的'\0',MQTT消息不需要该字符,因此用sizeof(message)-1
    rc = mosquitto_publish(mosq, NULL, "test/1", sizeof(message)-1, message, 0, false);
    if(rc != 0){
        printf("Failed to publish message! Error Code: %d\n", rc);
    }

    mosquitto_disconnect(mosq);
    mosquitto_destroy(mosq);

    mosquitto_lib_cleanup();
    return 0;
}

额外说明

  • 如果Broker启用了TLS加密,建议同时开启客户端的TLS支持(调用mosquitto_tls_set()等函数),避免账号密码在网络中明文传输
  • 编译时需链接libmosquitto库,示例编译命令:g++ mqtt_pub.cpp -o mqtt_pub -lmosquitto

内容的提问来源于stack exchange,提问作者Dean21

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 18:46:13