mosquitto
下载
/
解压 放到下面目录下
cd /root/mosquitto-auth-plug
cp config.mk.in config.mk
然后编辑 config.mk
BACKEND_MYSQL ?= yes
MOSQUITTO_SRC =/root/mosquitto-1.6.7 ##这是mosquitto源码目录
安装依赖
yum install gcc-c++
yum install libuuid-devel
yum install mysql+±devel.x86_64
yum install openssl-devel
yum install libc-ares-dev
编译
make
auth-plug.c:601:5: error: conflicting types for ‘mosquitto_auth_acl_check’
重要::
编译插件时报这个错误给搞死
根据文件查找对比插件的auth-plug.c 跟 源码里的mosquitto_plugin.h,其实auth-plug.c的那几个鉴权方法就相当于是重写mosquitto_plugin.h里的,
对比发现auth-plug.c 里的那些方法如‘mosquitto_auth_acl_check’里的一个参数struct mosquitto *client 这个不能有const,把const 去掉,不然会报类型不匹配无法编译
然后再make
在目录下得到auth-plug.so
把auth-plug.so放到/etc/mosquitto/plugin/ 里
配置 mosquitto
编辑mosquitto.conf
##不允许匿名访问
allow_anonymous false
auth_plugin /etc/mosquitto/plugin/auth-plug.so
auth_opt_backends mysql
auth_opt_host localhost
auth_opt_port 3306
auth_opt_user root
auth_opt_pass 123456
auth_opt_dbname mosquitto
auth_opt_userquery SELECT pw FROM users WHERE username = ‘%s’ LIMIT 1
auth_opt_superquery SELECT IFNULL(COUNT(*), 0) FROM users WHERE username = ‘%s’ AND super = 1
auth_opt_aclquery SELECT topic FROM acls WHERE (username = ‘%s’) AND (rw >= %d)
auth_opt_acl_cacheseconds 0 acl 缓存时间 默认300秒 0 表示不缓存
测试时一直报MqttException (128)
这是没有权限 acl表的权限值 要弄成对应的,这里要注意acl的缓存auth_opt_acl_cacheseconds ,否则会有大坑,一直测不准
数据库中ACL表上的读/写值必须在0到7之间变化。
0:无法访问
1:阅读
2:写
3:读写
4:订阅
5:阅读并订阅
6:撰写并订阅
7:读,写和订阅
一般读客户端用户就设置为5
装完后重新启动mosquitto就行了。
以后用户就直接由业务系统直接插入mysql,并且插入对应权限
附上java加密密码的代码
MosquittoPBKDF2.java
package com.dxf.demospringbootoss.mqtt;import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import java.nio.charset.Charset;
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;/*** This class implements functionality to generate and validate PBKDF2 hashes* for mosquitto-auth-plug.** @author Manuel Domínguez-Dorado - manuel.dominguez@enzinatec.es* @version 1.0*/
public class MosquittoPBKDF2 {/*** This method compares a plain password and a PBKDF2 password (in* mosquitto-auth-plug format) to know whether the password match the PBKDF2* hash.** @author Manuel Domínguez Dorado - manuel.dominguez@enzinatec* @param plainPassword Tha plain password to be compared to the PBKDF2* hash.* @param hashedPasword The PBKDF2 password in mosquitto-auth-plug format* (usualli it is stored in a MySQL database).* @return true, if password matches the PBKDF2 hash. false on the contrary.* @since 1.0*/public boolean isValidPassword(String plainPassword, String hashedPasword) {String[] encodedPassword = hashedPasword.split("\\$");int encodedIterations = Integer.parseInt(encodedPassword[2]);byte[] encodedSalt = encodedPassword[3].getBytes(Charset.forName("UTF-8"));String encodedHash = encodedPassword[4];SecretKeyFactory f = null;try {f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");} catch (NoSuchAlgorithmException e) {System.out.println("Need a Java implementation with cryptography.");}KeySpec ks = new PBEKeySpec(plainPassword.toCharArray(), encodedSalt, encodedIterations, MosquittoPBKDF2.KEY_LENGTH);SecretKey s = null;try {s = f.generateSecret(ks);} catch (InvalidKeySpecException e) {System.out.println("Encoded password is corrupt.");}return encodedHash.equals(Base64.getEncoder().encodeToString(s.getEncoded()));}/*** This method creates a new PBKDF2 password (in mosquitto-auth-plug format)* from a plain password.** @author Manuel Domínguez Dorado - manuel.dominguez@enzinatec* @param plainPassword The plain password used to generate the* corresponding PBKDF2 password (in mosquitto-auth-plug) format.* @return The generated PBKDF2 password in mosquitto-auth-plug format* (usually, it will be stored in a MySQL database).* @since 1.0*/public 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 "";}private static final int KEY_LENGTH = 24 * 8;private static final int SALT_LENGTH = 12;private static final int ITERATIONS = 901;
}
使用
MosquittoPBKDF2 pbkdf2Factory = new MosquittoPBKDF2();String hashedPassword = pbkdf2Factory.createPassword("123456");