1.准备插件

下载插件压缩包

mosquitto-auth-plug下载

将下载的压缩包

unzip   mosquitto-auth-plug-master.zip

或者直接从git上下载

git clone https://github.com/jpmens/mosquitto-auth-plug.git

2.安装准备插件

使用copy命令生成config.mk文件:

cp config.mk.in config.mk

编辑config.mk 根据需要选择合适的后台。我这里只使用mysql数据库验证用户,BACKEND_MYSQL这一行是yes,其余行都是no。在MOSQUITTO_SRC一行输入mosquitto的源码路径,比如MOSQUITTO_SRC =/root/mosquitto-1.4.4/

出现错误  fatal error: mysql.h: No such file or directory

可以使用安装mysql 插件

yum install mysql-devel -y

出现错误   conflicting types for ‘mosquitto_auth_unpwd_check’

由于auth-plug.c文件中格式错误,将const 删掉,如下

vim auth-plug.c

执行make


make

错误: In function ‘be_mysql_init’ unknown type name ‘my_bool’; did you mean ‘bool’


vim be-mysql.c

修改 my_bool 为 bool

执行完成后会生成 auth-plug.so

3.配置mosquitto配置文件

auth-plug.so移至mosquitto下

mv auth-plug.so /etc/mosquitto/

编辑配置文件

vim mosquitto.conf
# 监听端口配置
listener 1883                        
#protocol mqtt

allow_anonymous false


log_dest file /etc/mosquitto/log/mosquitto.log

#log_type error
#log_type warning
#log_type notice
#log_type information
#log_type all
log_type debug

connection_messages true

log_timestamp true


log_timestamp_format %Y-%m-%dT%H:%M:%S

# 配置用户密码
#password_file /etc/mosquitto/pwfile  

# 配置用户权限
#acl_file /etc/mosquitto/aclfile
 

#
##   __  __       ____   ___  _     
##  |  \/  |_   _/ ___| / _ \| |    
##  | |\/| | | | \___ \| | | | |    
##  | |  | | |_| |___) | |_| | |___ 
##  |_|  |_|\__, |____/ \__\_\_____|
##          |___/                   
##  
##                     
#
#auth_plugin /home/jpm/mosquitto-auth-plug/auth-plug.so
auth_plugin /etc/mosquitto/auth-plug.so
auth_opt_backends mysql
auth_opt_cdbname pwdb.cdb
auth_opt_host 127.0.0.1
auth_opt_port 3306
auth_opt_dbname username
auth_opt_user userpassword
auth_opt_pass GDJG@Gause_Sit
auth_opt_userquery SELECT pw FROM mqtt_users WHERE username = '%s'
auth_opt_superquery SELECT IFNULL(COUNT(*), 0) FROM mqtt_users WHERE username = '%s' AND super = 1
auth_opt_aclquery SELECT topic FROM mqtt_acls WHERE username = '%s'AND (rw >= %d)
#
#
## Usernames with this fnmatch(3) (a.k.a glob(3))  pattern are exempt from the
## module's ACL checking
#auth_opt_superusers S*
auth_opt_acl_cacheseconds 0

4.数据库管理

CREATE TABLE `mqtt_acls` (
  `id` int NOT NULL AUTO_INCREMENT,
  `username` varchar(25) NOT NULL,
  `topic` varchar(256) NOT NULL,
  `rw` int NOT NULL DEFAULT '1' COMMENT '1: read-only, 2: read-write',
  PRIMARY KEY (`id`),
  UNIQUE KEY `acls_user_topic` (`username`,`topic`(228))
) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

CREATE TABLE `mqtt_users` (
  `id` int NOT NULL AUTO_INCREMENT,
  `username` varchar(25) NOT NULL,
  `pw` varchar(128) NOT NULL,
  `super` int NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

5.java 加密工具

package com.shlm.test;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.util.Base64;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;

public class MosquittoPBKDF2 {

    private static final int KEY_LENGTH = 24 * 8;
    private static final int SALT_LENGTH = 12;
    private static final int ITERATIONS = 901;

    public static String createPassword(String plainPassword) {
        byte someBytes[] = new byte[MosquittoPBKDF2.SALT_LENGTH];
        Random randomGenerator = new Random();
        randomGenerator.nextBytes(someBytes);
        String encodedSalt = Base64.getEncoder().encodeToString(someBytes);

        SecretKeyFactory f = null;
        try {
            f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
        } catch (NoSuchAlgorithmException ex) {
            Logger.getLogger(MosquittoPBKDF2.class.getName()).log(Level.SEVERE, null, ex);
        }
        KeySpec ks = new PBEKeySpec(plainPassword.toCharArray(), encodedSalt.getBytes(), MosquittoPBKDF2.ITERATIONS, MosquittoPBKDF2.KEY_LENGTH);
        SecretKey s;
        try {
            s = f.generateSecret(ks);
            String encodedKey = Base64.getEncoder().encodeToString(s.getEncoded());
            String hashedKey = "PBKDF2$sha256$" + MosquittoPBKDF2.ITERATIONS + "$" + encodedSalt + "$" + encodedKey;
            return hashedKey;
        } catch (InvalidKeySpecException ex) {
            Logger.getLogger(MosquittoPBKDF2.class.getName()).log(Level.SEVERE, null, ex);
        }
        return "";
    }


    public static void main(String[] args) {
        System.out.println("test"+createPassword("test@1234"));   
    }
}