需求

  1. 在EMQ中添加认证插件,将到来的MQTT连接的ClientID、UserName、Password通过HTTP协议发送到认证服务器,用返回的数据决定是否允许该连接;
  2. 在连接时和断开时向服务器发送设备上线和离线信息,以支持设备管理的需要。

目前进度

3.12 基本已经掌握了插件开发的模式,但是目前发现也许可以组合几个已有的插件实现我们的需求,如果不用自己编码,虽然配置麻烦一点,但是还是能省下大量时间,初步设想是mysql认证/访问控制插件(主要采用访问控制功能)+http认证插件(加密算法认证)+webhook插件(上下线通知)

已有插件

EMQ中有一个使用http的认证插件,但使用它必须指定superuser认证服务器和访问权限服务器,不能单独开启普通用户认证功能,另外还需要集成上下线通知,我们只用到了他的三分之一功能,并且还需要额外功能,可以考虑的方案有两个,一是改写这个插件,禁用其他功能,并加上通知功能,另一个方案是自己写一个。

方案一的优点是插件部署方便,可以直接借原插件的壳,而不需要重新发布emq的整个release,缺点是代码修改很费时间,也不一定能切割出所有功能。

方案二的优点是编码简单,缺点是需要重新打包整个镜像。主要的挑战在于快速打包发布镜像。

实现路线

  1. 了解erlang基本语法,完成helloworld
  2. 编译运行EMQ的插件模板,尝试简单的修改
  3. 学习使用erlang的http库
  4. 在插件中加入http请求代码
  5. 完成简单的全流程
  6. 加入上下线hook
  7. 完成插件的config配置
  8. 整理代码,打包成独立插件并发布源码

Erlang helloworld

在erlang的官网上有一个quick start教程,半天时间基本可以看完所有关于erlang的基础语法,erlang跟golang很像,特别是并发部分,但是编写风格跟C/C++/JAVA系离得比较远,而golang则更靠近,更让我感到亲切。

EMQ插件模板

目前EMQ的插件都以独立仓库的形式开源,因此不需要clone整个emq项目,只需要clone一个插件模板就可以创建插件,而且直接在目录下make即可编译,如果增加库需要学习一下erlang库的链接配置方法。

模板里的代码已经加载了所有钩子(hook),并且在每一个钩子处打印提示信息,插入代码非常方便。

%% Called when the plugin application start
load(Env) ->
emqx:hook('client.connected', fun ?MODULE:on_client_connected/4, [Env]),
emqx:hook('client.disconnected', fun ?MODULE:on_client_disconnected/3, [Env]),
emqx:hook('client.subscribe', fun ?MODULE:on_client_subscribe/3, [Env]),
emqx:hook('client.unsubscribe', fun ?MODULE:on_client_unsubscribe/3, [Env]),
emqx:hook('session.created', fun ?MODULE:on_session_created/3, [Env]),
emqx:hook('session.resumed', fun ?MODULE:on_session_resumed/3, [Env]),
emqx:hook('session.subscribed', fun ?MODULE:on_session_subscribed/4, [Env]),
emqx:hook('session.unsubscribed', fun ?MODULE:on_session_unsubscribed/4, [Env]),
emqx:hook('session.terminated', fun ?MODULE:on_session_terminated/3, [Env]),
emqx:hook('message.publish', fun ?MODULE:on_message_publish/2, [Env]),
emqx:hook('message.delivered', fun ?MODULE:on_message_delivered/3, [Env]),
emqx:hook('message.acked', fun ?MODULE:on_message_acked/3, [Env]),
emqx:hook('message.dropped', fun ?MODULE:on_message_dropped/3, [Env]),

另外在acl(访问控制)的demo里有check函数,在收到连接时检查ClientID、UserName和Password,这里正是我所要的钩子,只需要在这里插入一个http的请求,通过response来判断是否允许连接就可以了。

我在插入http客户端代码的时候遇到了一个小问题:

我在init函数中增加了inets:start(),这是httpc说明中所说的初始化步骤,但是在加入这一步初始化后的http请求会发生错误,而不加入这个函数反而能正常获得response,因此我推测是emq本身早已执行了这一步初始化,因此不应当再次执行初始化。详细的原因我目前就不找了(能用就行)

后续:后面一直报相同的错,学习了一下erlang的报错机制后才发现错的是io:format()语句的参数格式,而不是因为inets:start(),以后还是要注意细节,这么小的一个问题浪费了我一整天的时间来调试,非常不值得。

Erlang HTTP client

Erlang作为爱立信为电信产业设计的语言,在网络方面的库非常发达,http是其标准库的一部分,这里是官方的使用说明

完成简单的全流程

在解决掉上述的小小问题之后,我成功在连接接入过程中插入了向外界发送http请求的接口。

插件配置

除了代码以外,还需要将整个插件单独整理出来,并且加入简单的配置功能,否则参数直接进代码会带来很大的麻烦。

emq的配置管理用了一个叫clique的库,文档少,官方库里只有readme里一个示例,很难搞清楚用法。

EMQ插件通过HTTP连接认证服务器实现认证的更多相关文章

  1. Spring Cloud实战 | 第九篇:Spring Cloud整合Spring Security OAuth2认证服务器统一认证自定义异常处理

    本文完整代码下载点击 一. 前言 相信了解过我或者看过我之前的系列文章应该多少知道点我写这些文章包括创建 有来商城youlai-mall 这个项目的目的,想给那些真的想提升自己或者迷茫的人(包括自己- ...

  2. EMQ插件组合实现物联网边缘平台的设备通信管理

    上一篇随笔我简单的记录了我对EMQ插件开发的了解过程,最后发现还是可以组合复用已有插件,因此这篇随笔用于记录使用的情况以及是否达到预期. 首先测试mysql认证插件的使用方式: emqx_auth_m ...

  3. freeradius整合AD域作anyconncet认证服务器

    一.服务器要求 Radius服务器:centos6.6.hostname.selinux  disabled.stop iptables AD域服务器:Windows Server 2008 R2 E ...

  4. Strophe.js连接XMPP服务器Openfire、Tigase实现Web私聊、群聊(MUC)

    XMPP(Extensible Messaging and Presence Protocol)是一种网络即时通讯协议,它基于XML,具有很强的扩展性,被广泛使用在即时通讯软件.网络游戏聊天.Web聊 ...

  5. SSH如何通过公钥连接云服务器

    导读 通常我们连接远程服务器(linux)windows下通过putty或xshell等工具远程连接.linux下可以直接通过ssh命令连接.其实这两者都是一致的,都是通过ssh协议进行传输. 如果我 ...

  6. Comet:基于 HTTP 长连接的“服务器推”技术解析

    原文链接:http://www.cnblogs.com/deepleo/p/Comet.html 一.背景介绍 传统web请求,是显式的向服务器发送http Request,拿到Response后显示 ...

  7. Comet:基于 HTTP 长连接的“服务器推”技术

    “服务器推”技术的应用 请访问 Ajax 技术资源中心,这是有关 Ajax 编程模型信息的一站式中心,包括很多文档.教程.论坛.blog.wiki 和新闻.任何 Ajax 的新信息都能在这里找到. c ...

  8. 转载:Comet:基于 HTTP 长连接的“服务器推”技术

    转自:http://www.ibm.com/developerworks/cn/web/wa-lo-comet/ 很多应用譬如监控.即时通信.即时报价系统都需要将后台发生的变化实时传送到客户端而无须客 ...

  9. Pure-ftpd无法连接到服务器 425错误

    今天是五一假期的前一天,闲来没事,打开自己的博客,发现很久没有备份数据了,由于工作方面的原因,自己慢慢的退出了技术界,但本人还是依然向往技术界啊!各位技术宅们,加油! 问题发现 当我打开FTP客户端软 ...

随机推荐

  1. python实现策略模式

    python实现策略模式 原文地址 1.策略模式概述 策略模式:定义一系列算法,把它们一一封装起来,并且使它们之间可以相互替换.此模式让算法的变化不会影响到使用算法的客户. 电商领域有个使用“策略”模 ...

  2. python-函数1(定义-作用-优势-返回值)

    python-函数1(定义-作用-优势-返回值) 1.面向对象的定义是靠-类>>class2.面向过程的定义是靠-过程 >>def3.函数式编程的定义是靠-函数>> ...

  3. PAT Advanced 1048 Find Coins (25 分)

    Eva loves to collect coins from all over the universe, including some other planets like Mars. One d ...

  4. UVa 10047 自行车 状态记录广搜

    每个格子(x,y,drection,color) #include<iostream> #include<cstdio> #include<cstring> #in ...

  5. ubuntu 配置smb后无法访问

    配置如下 [/gscloud] path = /gscloud browseable = yes writable = yes guest ok = yes read only = no create ...

  6. u-boot log_init函数分析

    log_init, int log_init(void){    struct log_driver *drv = ll_entry_start(struct log_driver, log_driv ...

  7. 【洛谷P2602】数字计数

    题目大意:求 [a,b] 中 0-9 分别出现了多少次. 题解:看数据范围应该是一个数位dp. 在 dfs 框架中维护当前的位置和到当前位置一共出现了多少个 \(x,x\in [0,9]\).因此,用 ...

  8. eclipse安装hibernate tools插件

    第一步:在eclipse菜单中选择Help>Install New Software,弹出安装插件的窗口,如图: 在Work with:后面输入http://download.jboss.org ...

  9. 【NOIP2016提高A组模拟9.14】数列编辑器

    题目 分析 比赛上,没有注意到询问只询问光标前面,于是只打了个暴力. 因为询问只询问光标前面,首先,当光标向后每移动到一个位置,顺便将这个位置的前缀和,和最大前缀和求出来. 总之,模拟 #includ ...

  10. time时间库使用示例

    time时间库主要有以下几个方法 1. 生成struct_time ,然后就可以很方便的获取到年月日,时分秒等信息 time.localtime() 2. 生成时间戳 time.time() 3. 将 ...