tlmqtt:如何基于责任链模式的高效认证

tlmqtt 是一款基于Java开发的轻量级高并发MQTT Broker,采用NettyProject Reactor实现异步通信,完整支持MQTT 3.1.1 协议,包括QoS 消息分级、主题通配符、消息持久化等核心功能。项目采用模块化设计,提供认证(文件/数据库/HTTP)数据桥接(Kafka/MySQL )和存储(内存/Redis)等可扩展组件,支持MQTTWebSocket 双协议接入。具备生产级特性如SSL加密、会话恢复及高并发处理能力,适用于物联网和实时通信场景。

认证

mqtt协议规定了CONNECT 包含有UsernamePassword字段。实现可以选择如何使用这些字段的内容。他们也可能提供自己的认证机制,使用额外的认证系统。 而tlmqtt 实现了基本文件mysqlhttp接口的3种认证方式,并且提供了扩展让用户自行去实现认证方式并添加到认证链中,其中只要有任何一个认证通过了,那么此次客户端连接就是通过的

tlmqtt 认证原理

tlmqtt 存在一个抽象类AbstractTlAuthentication它定义了认证相关的抽象方法,有具体的认证器去实现

php 复制代码
  /**
     * 认证接口
     * @author hszhou
     * @datetime: 2025-05-10 10:51:55
     * @param username 用户名
     * @param password 密码
     * @return boolean 是否成功
     **/
    abstract public boolean authenticate(String username, String password);

    /**
     * 是否启用了该认证器
     * @author hszhou
     * @datetime: 2025-05-12 10:11:26
     * @return boolean 是否启用
     **/
    abstract public boolean enabled();


    /**
     * 添加新的认证主体
     * @author hszhou
     * @datetime: 2025-05-15 17:53:17
     * @param object 添加的认证实体
     **/
    abstract public void add(Object object);

NoneAuthenticationService

tlmqtt 是可以通过一个配置来进行关闭客户端的认证的。

yml 复制代码
auth:
 enabled: true #是否开启认证 false就是关闭认证

其实现原理就是通过NoneAuthenticationService这个认证器。也是认证链中的第一个认证器。

typescript 复制代码
   @Override
   public boolean authenticate(String username, String password) {
       return true;
   }

其主要实现了authenticate方法返回的是trueNoneAuthenticationService并不关心客户端的用户名和密码,也就是无论用户名和密码是什么,他都不会在意,只会返回true。表示认证通过,而enabled方法返回的就是是否开启,一旦开启了,那么这个authenticate就会执行。由于处于认证链的首位。只要通过了就不会执行其他的认证了。

FixTlAuthentication

FixTlAuthentication是基于固定用户的认证方式。其固定的用户的配置方式有2种, 第一种是基于文件的,这种方式是提前将用户写入到配置文件中

yml 复制代码
auth:
  enabled: true #是否开启认证 false就是关闭认证
  user: #开启认证后fix的认证信息
    - username: watson
      password: 12345
    - username: zhouhs
      password: 12345

第二种方式是基于编程的tlmqtt启动引导类支持动态添加用户

java 复制代码
tlBootstrap.setFixUser(Collections.singletonList(new TlUser("admin","12345")))

FixTlAuthentication的内部维护了一个用户列表,authenticate方法就是将客户端的用户名与密码将内部的用户列表继续依次匹配。只要有任何一个匹配成功就返回。

java 复制代码
    public boolean authenticate(String username, String password) {
        if(users.isEmpty()){
            return false;
        }
        for (TlUser user : users) {
            if (user.getUsername().equals(username) && user.getPassword().equals(password)) {
                log.debug("username = 【{}】,password = 【{}】 pass",username,password);
                return true;
            }
        }
        return false;
    }

而编程式的添加用户就是往内部的用户列表中添加用户

java 复制代码
    @Override
    public void add(Object object) {

        if( object instanceof TlUser){
            log.debug("join fix authentication user 【{}】",object);
            this.users.add((TlUser) object);
        }
    }

HttpTlAuthentication

HttpTlAuthentication认证器是基于http请求的认证器。也是tlmqtt 的内置认证器之一。通过将用户名与密码当做参数请求第三方的API进行认证。只要API返回的状态码为200 ,注意的是这里的状态码200HTTP的状态码,而不是第三方系统自己定义的200 . tmqtthttp请求封装成一个对象HttpEntityInfo。里面有API的地址,参数等等信息

java 复制代码
public class HttpEntityInfo {

    /**请求的地址*/
    private String url;
    /**方法类型 post或者get*/
    private String method;
    /**请求头*/
    private HashMap<String, String> headers;
    /**用户的参数 例如 参数是uname 与pwd 那么这个params的参数就是("username","uname") ("password","pwd")*/
    private HashMap<String,String> params;

}

HttpTlAuthentication将认证接口大致分为3类,

  • POST请求的form表单提交
  • POST请求的json数据提交
  • GET请求

最终只要请求返回的是200就认证认证成功

HttpTlAuthentication认证过滤器不单单可以设置一个API。可以通过多个API接口组成的集合进行认证。其内部维护了一个HttpEntityInfo的集合。只要任何一个API通过,及认证通过

java 复制代码
   private final List<HttpEntityInfo> httpEntityInfos;

HttpTlAuthentication提供了动态添加http接口的方式

java 复制代码
    @Override
    public void add(Object object) {
        if (object instanceof HttpEntityInfo) {
            this.httpEntityInfos.add((HttpEntityInfo) object);
        }
    }

使用方式

java 复制代码
  HttpEntityInfo entityInfo = AuthenticationHttpProvider.formLogin();
  HttpEntityInfo login = AuthenticationHttpProvider.getLogin();
  tlBootstrap.addAuthEntity(entityInfo)
              .addAuthEntity(login)

SqlTlAuthentication

SqlTlAuthentication认证器是基于mysql数据库的认证,tlmqttSqlTlAuthentication的数据封装成了一个SQL对象SqlEntityInfo

java 复制代码
  /**地址*/
    private String host;

    /**端口号*/
    private String port;

    /**用户名*/
    private String username;

    /**密码*/
    private String password;

    /**数据库名*/
    private String  database;

    /**表名*/
    private String table;

    /**用户名字段*/
    private String usernameColumn;

    /**密码字段*/
    private String passwordColumn;

    private String driverClassName;

如果需要使用到SqlTlAuthentication认证过滤器,就需要添加相应的SqlEntityInfoSqlEntityInfo设置数据库的地址,表名和用户名和密码的字段。然后其内部维护了一个SqlEntityInfo集合,与http认证器一致,只要有任何一个认证通过即可,当用户设置成功后,tlmqtt 会执行内部的sql语句并替换相应的参数

sql 复制代码
 private static final String SQL = "SELECT COUNT(*) FROM %s WHERE %s = ? AND %s = ?";

SqlTlAuthentication提供动态方法新增SqlEntityInfo的方式。使用方法

java 复制代码
SqlEntityInfo sqlEntityInfo = AuthenticationMysqlProvider.providerDemo();
tlBootstrap .addAuthEntity(sqlEntityInfo)    

可扩展的认证链

当上述认证器不满足系统的认证方式,tlmqtt 提供了可扩展的认证器。是需要用户继承AbstractTlAuthentication类即可。然后实现authenticate方法。然后通过辅助引导类TlBootstrapaddAuthentication方法即可。

实现AbstractTlAuthentication类

java 复制代码
@Slf4j
public class NoneA extends AbstractTlAuthentication {
    @Override
    public boolean authenticate(String username, String password) {
        return true;
    }

    @Override
    public boolean enabled() {
        return true;
    }

    @Override
    public void add(Object object) {

    }
}

添加认证器

java 复制代码
 tlBootstrap.addAuthentication(new NoneA())

这样就可以将自定义的认证器添加到tlmqtt的整个认证体系中。

结语

欢迎通过以下方式参与项目共建:

  1. 提交 Issue:反馈 Bug 或提出功能建议
  2. 提交 PR:优化代码或新增功能(建议先创建 Issue 沟通方案)
  3. Star/Fork:支持项目持续发展

联系方式:

tlmqtt致力于为物联网开发者提供轻量、高效的 MQTT 消息服务,期待您的加入! 🚀

本文由博客一文多发平台 OpenWrite 发布!

相关推荐
厨 神10 小时前
物联网-ESP8266
物联网
董技叔软件开发公司10 小时前
物联网应用开发技术趋势与实践指南
物联网·物联网开发·物联网系统开发
TDengine (老段)16 小时前
TDengine 集群部署及启动、扩容、缩容常见问题与解决方案
大数据·数据库·物联网·时序数据库·iot·tdengine·涛思数据
熬夜的猪仔18 小时前
【Freertos实战】零基础制作基于stm32的物联网温湿度检测(教程非常简易)持续更新中.........
stm32·嵌入式硬件·物联网
网易独家音乐人Mike Zhou1 天前
【Linux应用】开发板USB共享网络,网线或USB以太网共享网络(局域网连接PC和开发板,实现PC给开发板共享网络,USB通过NDIS驱动共享)
linux·网络·单片机·mcu·物联网·嵌入式·iot
涛思数据(TDengine)1 天前
时序数据库 TDengine × SSRS:专为工业、能源场景打造的报表解决方案
大数据·数据库·物联网·时序数据库·tdengine
TESmart碲视1 天前
USB一线连多屏?Display Link技术深度解析
stm32·单片机·嵌入式硬件·物联网·计算机外设·电脑·智能硬件
时序数据说2 天前
时序数据库的存储之道:从数据特性看技术要点
大数据·数据库·物联网·开源·时序数据库·iotdb
行之无边2 天前
零基础入门物联网-远程门禁开关:硬件介绍
物联网
TDengine (老段)2 天前
TDengine 数据库建模最佳实践
大数据·数据库·物联网·时序数据库·tdengine·涛思数据