在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
相关产品推荐
相关产品推荐

