自定义插件逻辑
本页面介绍如何通过修改 src/my_emqx_plugin.erl 文件中的默认模板逻辑,来自定义你的 EMQX 插件。该模板默认注册了所有可用的 EMQX hook。你应当移除不需要的 hook,并在保留的回调中实现自定义逻辑。
注册 Hook 函数
例如,如果你希望添加认证和权限控制逻辑,可以按如下方式定义 my_emqx_plugin:hook/0 函数:
hook() ->
emqx_hooks:add('client.authenticate', {?MODULE, on_client_authenticate, []}, ?HP_HIGHEST),
emqx_hooks:add('client.authorize', {?MODULE, on_client_authorize, []}, ?HP_HIGHEST).其中,on_client_authenticate/2 用于处理客户端认证,on_client_authorize/4 用于授权。
由于同一个 hook 函数可能被 EMQX 和其他自定义插件同时挂载,因此在注册时需要指定执行顺序。?HP_HIGHEST 表示当前 hook 函数的优先级最高,将被最先执行。
示例:添加访问控制逻辑
以下是一个实现基础访问控制的示例:
%% 仅允许客户端 ID 由字母、数字或下划线组成的连接。
on_client_authenticate(_ClientInfo = #{clientid := ClientId}, Result) ->
case re:run(ClientId, "^[A-Za-z0-9_]+$", [{capture, none}]) of
match -> {ok, Result};
nomatch -> {stop, {error, banned}}
end.
%% 客户端只能订阅 /room/{clientid} 格式的主题,但可以向任意主题发送消息。
on_client_authorize(_ClientInfo = #{clientid := ClientId}, subscribe, Topic, Result) ->
case emqx_topic:match(Topic, <<"/room/", ClientId/binary>>) of
true -> {ok, Result};
false -> stop
end;
on_client_authorize(_ClientInfo, _Pub, _Topic, Result) -> {ok, Result}.上述逻辑保证:
- 只有合法 ID 的客户端可以连接。
- 客户端可以发布到任意主题。
- 客户端只能订阅自己对应的
/room/{clientid}主题,从而实现简易的聊天室机制。
TIP
- 请在 EMQX 配置中设置
authorization.no_match = deny以阻止未命中的访问请求。 - 如需基于文件的授权规则,请参考 ACL 文件。
添加配置模式(可选)
从 EMQX 5.7.0 起,插件配置可以通过 REST API 动态管理。为启用该功能并确保配置校验,你的插件应包含:
- 一个用于校验配置结构的 Avro 模式文件,路径为
priv/config_schema.avsc。该文件必须符合 Apache Avro 规范。 - 一个默认配置文件
priv/config.hocon,其内容需满足 Avro 模式定义的规则。
运行时,配置更新将写入 data/plugins/<PLUGIN_NAME>/config.hocon,旧版本配置文件会自动备份。
TIP
你可以参考插件项目目录中的示例文件:
priv/config.hocon.examplepriv/config_schema.avsc.examplepriv/config_schema.avsc.enterprise.example(包含 UI 定义)priv/config_i18n.json.example(用于国际化)
这些文件可作为构建插件配置模式和 UI 的模板。
定义声明式 UI(可选)
Avro 模式文件可以包含 $ui 字段,用于定义配置项在 EMQX Dashboard 中的展示形式。插件用户可以通过自动生成的动态表单进行配置。
还可以通过一个可选的国际化(i18n)配置文件进行语言支持,路径为 priv/config_i18n.json,格式为键值对,例如:
{
"$msgid": {
"zh": "消息",
"en": "Message"
}
}在 $ui 配置中使用以 $ 开头的 $msgid 可实现字段名称、描述、校验提示等元素的多语言支持。
配置项字段说明
声明式 UI 支持多种字段类型和自定义组件,可动态生成配置表单。以下是各组件说明及配置方式:
component必填。指定用于展示和配置不同类型值的组件类型。支持的组件包括:组件名称 描述 input文本输入框(短文本或字符串) input-password密码输入框,内容不可见 input-number数字输入框,仅允许输入数字 input-textarea多行文本输入区域 input-array数组输入框,逗号分隔的值,支持字符串或数字数组 switch布尔值开关组件 select下拉选择框,用于枚举类型 code-editor代码编辑器,用于特定格式(如 SQL、JSON) key-value-editor用于编辑 Avro map 的键值对编辑器 maps-editor用于编辑 Avro 对象数组的编辑器 label必填。字段的显示名称,支持$msgid国际化;如未配置 i18n,显示原始文本。description可选。字段描述,支持$msgid国际化;如未配置 i18n,显示原始文本。flex必填。字段在栅格布局中所占比例:24 表示整行,12 表示半行。required可选。是否为必填字段。format(仅适用于code-editor) 可选。指定支持的代码格式,如sql或json。options(仅适用于select) 可选。列出可选项,对应 Avro Schema 中的符号。例如:json[ { "label": "$mysql", "value": "MySQL" }, { "label": "$pgsql", "value": "postgreSQL" } ]items(仅适用于maps-editor) 可选。用于指定编辑对象数组时的字段名和描述,例如:json{ "items": { "optionName": { "label": "$optionNameLabel", "description": "$optionDesc", "type": "string" }, "optionValue": { "label": "$optionValueLabel", "description": "$optionValueDesc", "type": "string" } } }rules可选。定义字段的校验规则,可配置多个规则。支持的类型包括:pattern:使用正则表达式校验字段值;range:对数值字段进行范围校验,可设置min和max;length:限制输入字符长度,支持配置minLength和maxLength;message:校验失败时显示的错误提示,支持$msgid国际化。
校验规则示例
以下是一些校验规则配置示例。更多例子请参考 priv/config_schema.avsc.example 文件:
{
"rules": [
{
"type": "pattern",
"pattern": "^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])(\\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]))*$",
"message": "$hostname_validate"
}
]
}{
"rules": [
{
"type": "range",
"min": 1,
"max": 65535,
"message": "$port_range_validate"
}
]
}{
"rules": [
{
"type": "length",
"minLength": 8,
"maxLength": 128,
"message": "$password_length_validate"
},
{
"type": "pattern",
"pattern": "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)[a-zA-Z\\d]*$",
"message": "$password_validate"
}
]
}将 Avro 模式文件和 i18n 配置文件一同打包进插件,可以确保它们在插件构建和发布过程中被正确使用。在插件代码中,可通过 emqx_plugins:get_config/1,2,3,4 函数读取配置项。