首页/新闻资讯/正文详情

EMQX client_attrs_init 支持 password 变量:用 JWT 密码初始化客户端属性

发布时间:2026/9/23 13:25:19 来源:云帆数科 栏目:资讯中心
EMQX client_attrs_init 支持 password 变量:用 JWT 密码初始化客户端属性
EMQX client_attrs_init 支持 password 变量用 JWT 密码初始化客户端属性【免费下载链接】emqxThe most scalable and reliable MQTT broker for AI, IoT, IIoT and connected vehicles项目地址: https://gitcode.com/gh_mirrors/em/emqx导读本篇文章围绕 EMQX 开源仓库中的变更记录 changes/ee/fix-16684.en.md 展开讲解mqtt.client_attrs_init表达式的一个关键能力增强在客户端属性初始化表达式中可以直接引用 CONNECT 报文携带的password。在此之前client_attrs_init的执行时机早于密码被写入渲染上下文导致依赖密码的表达式例如把密码当作 JWT 传给jwt_value提取声明无法解析。读完本文你将掌握client_attrs_init的完整配置方式、渲染上下文中可用的全部变量以及如何把 JWT 型密码中的子声明sub、user.name 等提取为客户端属性再用于挂载点、认证与授权模板渲染。一、变更背景什么是 client_attrs_initclient_attrs_init是 EMQX MQTT 配置mqtt命名空间下的一项能力用于在客户端连接建立时根据连接上下文计算一组客户端属性client attributes。这些属性会以client_attrs.{NAME}的形式存放并可以在后续的模板渲染中使用例如渲染挂载点mountpoint实现按租户隔离主题命名空间如mountpoint ${client_attrs.tns}/渲染 HTTP 认证 / 授权请求的请求体或头作为桥接、消息处理等场景中的变量来源。其配置结构定义在 apps/emqx/src/emqx_schema.erlfields(client_attrs_init) - [ {expression, emqx_variform:sc(#{desc ?DESC(client_attrs_init_expression)})}, {set_as_attr, sc(binary(), #{ desc ?DESC(client_attrs_init_set_as_attr), validator fun restricted_string/1 })} ];每个初始化条目由两个字段构成字段类型说明expression字符串一行 variform 表达式可以是函数调用支持嵌套、也可以是直接变量引用例如nth(1, tokens(clientid, .))提取 clientid 的点分前缀set_as_attr字符串计算结果存放的客户端属性名之后可通过client_attrs.{NAME}引用配置位于mqtt命名空间下见 apps/emqx/src/emqx_schema.erl以数组形式配置多个条目。set_as_attr还带有restricted_string校验器保证属性名符合安全规范。二、修复前的问题password 不在渲染上下文中按照变更记录 changes/ee/fix-16684.en.md 的描述此前的实现存在一个时序缺陷Previously,client_attrs_initran before password was added to the rendering context, so expressions depending on password could not be resolved.即client_attrs_init表达式求值发生在密码被加入渲染上下文之前。因此任何引用password的表达式都会解析失败。而密码恰恰是很多场景下的关键输入——尤其在密码本身就是 JWT例如设备接入使用 JWT 作为口令时我们希望直接从密码中提取sub、user.name、user.profile.age等声明来初始化客户端属性用于后续的租户识别、模板渲染。修复前这类表达式无法工作。三、修复后的实现password 进入渲染上下文修复的核心位于连接通道模块 apps/emqx/src/emqx_channel.erlget_client_attrs_init_config(Zone) - get_mqtt_conf(Zone, client_attrs_init, []). maybe_set_client_initial_attrs(ConnPkt, #{zone : Zone} ClientInfo, ConnInfo) - case get_client_attrs_init_config(Zone) of [] - {ok, ClientInfo}; Inits - UserProperty get_user_property_as_map(ConnPkt), Password get_connect_password(ConnPkt), RenderCtx client_attrs_init_render_ctx( ClientInfo#{user_property UserProperty, password Password}, ConnInfo ), Attrs0 maps:get(client_attrs, ClientInfo, #{}), Attrs1 initialize_client_attrs(Inits, RenderCtx), {ok, ClientInfo#{client_attrs maps:merge(Attrs0, Attrs1)}} end.关键变化通过get_connect_password/1从 CONNECT 报文中取出密码见 apps/emqx/src/emqx_channel.erl即#mqtt_packet_connect{password Password}将password与user_propertyCONNECT 报文的用户属性映射一起并入渲染上下文RenderCtxinitialize_client_attrs/2对每个条目执行emqx_variform:render(Variform, ClientInfo)并把结果按set_as_attr命名合并进client_attrs。从执行时机看maybe_set_client_initial_attrs位于enrich_client/3的流水线中见 apps/emqx/src/emqx_channel.erl顺序为设置 username → 设置 bridge_mode → 可能用 username 作为 clientid → 分配 clientid →初始化客户端属性→ clientid 覆盖。源码注释明确说明attr init should happen after clientid and username assign属性初始化应发生在 clientid 与 username 赋值之后、clientid override should happen after client_attrs is initializedclientid 覆盖应发生在属性初始化之后。这意味着在属性初始化表达式中clientid、username已经是最终值同时password也已可用。四、实战用 jwt_value 从密码中提取 JWT 声明jwt_value/2是 variform 提供的内置函数用于从 JWT token 中按点分路径提取声明值实现在 apps/emqx_utils/src/emqx_variform_bif.erl。其典型用法jwt_value(Token, sub)提取顶层声明jwt_value(Token, user.name)提取嵌套 JSON 对象中的字段jwt_value(Token, user.profile.age)提取更深层路径。从实现看jwt_value会把 token 按.拆分为三段header.payload.signature对 payload 做 base64url 解码后按点分路径取值若 token 结构非法会抛出invalid_jwt_token。需要说明的是该函数只解码 payload 并取值不做签名校验因此它适合在认证之前做属性预提取而不应单独作为身份认证手段。修复后即可在client_attrs_init表达式中引用password并喂给jwt_value例如在emqx.conf中mqtt { client_attrs_init [ { # 从 JWT 型密码中提取 sub 声明作为用户 ID expression jwt_value(password, sub) set_as_attr user_id }, { # 提取嵌套声明 user.name expression jwt_value(password, user.name) set_as_attr username_from_jwt } ] }表达式为单行 variform 语法支持函数嵌套调用与直接变量引用字符串字面量使用单引号与tokens(clientid, .)的写法一致。初始化完成后这些属性即可在其它模板中通过${client_attrs.user_id}、${client_attrs.username_from_jwt}引用例如挂载点mountpoint ${client_attrs.user_id}/实现按 JWT 主体隔离主题命名空间HTTP 认证 / 授权请求模板在请求体或 URL 中携带${client_attrs.user_id}作为查询参数。五、渲染上下文可用变量一览结合 schema 文档 rel/i18n/emqx_schema.hocon 与源码实现client_attrs_init表达式的预绑定变量包括变量来源说明clientidMQTT CONNECT客户端 ID属性初始化前已赋值usernameMQTT CONNECT用户名属性初始化前已赋值passwordMQTT CONNECT本次修复新增CONNECT 报文中的密码可喂给jwt_valueuser_property.{NAME}MQTT v5 CONNECTCONNECT 报文中的用户属性zone监听器配置客户端所在配置区zonelistener监听器配置监听器 ID如tcp:defaultcn/cert_common_nameTLS 证书客户端证书通用名直连或经 proxy-protocol v2 的 TLS 客户端dn/cert_subjectTLS 证书客户端证书主体DNcert_san.dns/cert_san.ip/cert_san.email/cert_san.uriTLS 证书直连 TLS 客户端的证书主题备用名称SANpeersniTLS 握手客户端发送的 SNI此外渲染上下文构建时还会合并证书 SAN 与 CN/DN 处理见 apps/emqx/src/emqx_channel.erl。需要注意的是仓库快照中的 schema 文档变量清单未显式列出password但源码已在maybe_set_client_initial_attrs/3中将其写入渲染上下文这是本次变更的实际行为。六、测试与行为验证仓库中的测试为这一机制提供了可验证依据客户端属性初始化的单元级验证位于 apps/emqx/test/emqx_channel_SUITE.erlt_client_attrs_with_control_chars_dropped直接调用emqx_channel:initialize_client_attrs/2传入#{set_as_attr ..., expression ...}列表验证渲染结果会按属性名合并且产生 C0/C1 控制字符例如从非严格模式的 MQTT v5 用户属性带入 CRLF的属性会被丢弃防止${client_attrs.tns}流入 HTTP 模板造成注入。jwt_value/2内置函数的单测位于 apps/emqx_utils/test/emqx_variform_bif_tests.erl覆盖了 JWT 声明提取、嵌套路径user.name、user.profile.age等场景。若要自行验证本次修复可在配置了上述client_attrs_init的 EMQX 节点上用一个密码为 JWT 的 MQTT 客户端发起连接然后通过 Dashboard 的客户端详情或client_attrs相关查询确认user_id等属性已按预期生成也可在 HTTP 认证 / 授权桥的请求模板中直接引用${client_attrs.user_id}观察实际透传值。七、注意事项密码仅用于表达式求值password只在client_attrs_init渲染阶段进入上下文除非表达式显式将其写入结果否则密码不会存入client_attrs也不会被持久化到属性中。jwt_value 不做签名校验用它做属性预提取是安全的但完整的 JWT 认证应交给 JWT 认证器如emqx_auth_jwt在认证阶段完成。单行表达式限制expression必须是单行表达式支持函数嵌套调用与直接变量引用不支持用户自定义变量绑定或自定义函数参见 rel/i18n/emqx_schema.hocon 的说明。属性名受校验set_as_attr通过restricted_string校验异常或含控制字符的渲染结果会被丢弃避免下游模板注入风险。参考变更记录changes/ee/fix-16684.en.md核心实现apps/emqx/src/emqx_channel.erl配置 schemaapps/emqx/src/emqx_schema.erl内置函数 jwt_valueapps/emqx_utils/src/emqx_variform_bif.erl配置项说明rel/i18n/emqx_schema.hocon相关测试apps/emqx/test/emqx_channel_SUITE.erl、apps/emqx_utils/test/emqx_variform_bif_tests.erl【免费下载链接】emqxThe most scalable and reliable MQTT broker for AI, IoT, IIoT and connected vehicles项目地址: https://gitcode.com/gh_mirrors/em/emqx创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关推荐

弱电系统集成项目经理证有必要报班吗?从报名学习到考试拿证,报考全攻略
弱电系统集成项目经理证有必要报班吗?从报名学习到考试拿证,报考全攻略

弱电系统集成项目经理是弱电工程领域的复合管理岗位,负责项目从设计到交付的全流程。想考证进阶,报不报班?本文围绕弱电系统集成项目经理证,把自学与报班的差距、费用、选班要点和报考流程讲透。 先说结论:集成项目经理… · 2026/9/23 13:25:19

PaddleNLP DuReader 评测指标模块深入解析:从答案抽取到 ROUGE-L/BLEU-4 评分
PaddleNLP DuReader 评测指标模块深入解析:从答案抽取到 ROUGE-L/BLEU-4 评分

人工智能大模型预训练微调LoRARLHF强化学习分布式训练 【免费下载链接】PaddleNLP Easy-to-use and powerful LLM and SLM library with awesome model zoo. 项目地址: https://gitcode.com/gh_mirrors/pa/PaddleNLP 点击查看 免费下载 导读 本文围绕 PaddleNLP 中… · 2026/9/23 13:25:19

Cytoscape.js 缩放控制 API:zoomingEnabled() 用法、初始化选项与底层交互机制详解
Cytoscape.js 缩放控制 API:zoomingEnabled() 用法、初始化选项与底层交互机制详解

Cytoscape.js 缩放控制 API:zoomingEnabled() 用法、初始化选项与底层交互机制详解 【免费下载链接】cytoscape.js Graph theory (network) library for visualisation and analysis 项目地址: https://gitcode.com/gh_mirrors/cy/cytoscape.js 导读 zoomin… · 2026/9/23 13:25:19

字幕下载踩坑3次后总结:Python完整示例源码解析
字幕下载踩坑3次后总结:Python完整示例源码解析

字幕下载踩坑3次后总结:Python完整示例源码解析 看了一堆教程还是不会写项目?别急,问题往往出在环境配置和依赖冲突上。很多教程只给代码,不给“为什么”,导致你复制粘贴就报错。 今天这篇不玩虚的,直接拆解一个基于 PyPI 官方包… · 2026/9/23 14:07:32

PLC控制步进电机硬接线实战平台搭建
PLC控制步进电机硬接线实战平台搭建

简介:本资源是一份面向自动化专业本科生及PLC初学者的课程设计实践说明书,聚焦PLC与步进电机测试平台的全流程搭建,解决人机交互式电机性能测试中的机械设计、电气布线、PLC编程(S7-200 SMART)与组态王(Kin… · 2026/9/23 14:07:31

视频压缩编码保姆级教程:搞定这5个高频面试题
视频压缩编码保姆级教程:搞定这5个高频面试题

视频压缩编码保姆级教程:搞定这5个高频面试题 配环境卡了三天?FFmpeg 装不上,libx264 编译报错,Python 库版本冲突。这种崩溃感我太懂了。… · 2026/9/23 14:07:24

大语言模型技术发展与应用场景探索研究
大语言模型技术发展与应用场景探索研究

刚接触一个新领域,最怕的就是迷失在海量的外国文献里,读了很多篇还是理不清脉络。我曾经也以为“研究现状”只能靠逐篇阅读、手动总结,直到发现了一些能生成“知识图谱”的神器。它们能让你像开了上帝视角一样,瞬间看清一个领域的… · 2026/9/23 14:07:24

C++ MFC五子棋人机对战:从课程设计到可运行桌面程序
C++ MFC五子棋人机对战:从课程设计到可运行桌面程序

简介:这是一份面向高校C课程学习者与Windows桌面开发入门者的期末大作业参考方案,围绕MFC框架实现人机对战五子棋,帮助读者理解面向对象设计、界面开发与博弈算法的结合方式。压缩包共36个文件,约160KB,以cpp与h源码为… · 2026/9/23 14:07:18

上市公司新闻文本分类:从数据清洗到TF-IDF模型实战
上市公司新闻文本分类:从数据清洗到TF-IDF模型实战

简介:这份源码面向具备一定Python基础的金融数据分析学习者与量化研究者,提供一套完整的上市公司新闻文本分析与分类预测方案,解决财经新闻自动抓取、特征提取与模型分类的实践问题。资源包共21个文件,以17个Python源代码文件为核… · 2026/9/23 14:07:18

3招搞定手机怎么下载微信面试难题实战项目解析
3招搞定手机怎么下载微信面试难题实战项目解析

3招搞定手机怎么下载微信面试难题实战项目解析 面试被问“手机怎么下载微信”背后的原理,90%的人答不上来。别笑,这看似弱智的问题,实则是考察你对移动应用分发机制、安全校验及网络协议理解的试金石。我带过不少校招新人,他们背了八股文,却连一个A… · 2026/9/23 0:00:03

你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型
你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型

你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 面试被问“高并发下如何保证消息不丢失”,你张口就是“用Redis”,结果面试官追问“如果Redis宕机了怎么办”,你瞬间卡壳。这种场景太常见了,很多新手在背八股文时,只记住了技术名词… · 2026/9/23 0:00:29

Win7无线热点配置工具源码解析:解决API失效的3个实战技巧
Win7无线热点配置工具源码解析:解决API失效的3个实战技巧

Win7无线热点配置工具源码解析:解决API失效的3个实战技巧 Win7无线热点配置工具在Win10/11上跑不动?不是你的问题,是版本升级后 API 全变了。很多老项目里的 netsh wlan… · 2026/9/23 0:00:36

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码