Apache NiFi ExecuteScript编写JS解密JWT报错求助
NiFi JWE解密脚本报错排查
报错根因
- 脚本语法不兼容运行环境:NiFi内置的JavaScript执行引擎(Java 8/11自带的Nashorn)不支持ES6规范的
async/await、块级const/let声明特性,你在if块内定义async函数、用const声明变量,引擎无法识别对应关键字,直接抛出语法异常。 - 处理器用法混淆:你提到使用
ExecuteCommand处理器,但代码里调用了session、flowFile这类仅在ExecuteScript脚本处理器里才存在的API,ExecuteCommand是用来调用外部系统命令的,本身不提供NiFi流文件操作接口。 - 代码逻辑错误:定义的
decryptJWE函数从未被调用;return语句写在流文件属性写入逻辑前面,后续属性赋值永远不会执行;传入的JWK私钥格式非法,把多个字段拼成了单个字符串;属性写入时传的是固定字符串'jweToken',不是解密后的实际结果。
修复方案
方案1:使用ExecuteScript处理器(直接在NiFi内写JS脚本)
适配Nashorn引擎语法,放弃async/await,改用Promise链式调用处理异步逻辑,注意异步回调内必须完成流文件转移:
// 提前将node-jose的浏览器端打包文件放到NiFi服务器可访问路径,通过load加载 load('/opt/nifi/scripts/node-jose.min.js'); var flowFile = session.get(); if (flowFile != null) { var jweToken = flowFile.getAttribute('token'); // 替换为合法的JWK私钥结构,必须补全kty、d、dp、dq、qi等必填字段 var privKeyJwks = { kty: "RSA", p: "aaaaaabbbccccc", q: "cddbcbvbvbmm" }; JWK.asKey(privKeyJwks) .then(function(privKey) { return JWE.createDecrypt(privKey).decrypt(jweToken); }) .then(function(decryptRes) { var plainText = decryptRes.plaintext.toString(); flowFile = session.putAttribute(flowFile, 'decrypted_token', plainText); session.transfer(flowFile, REL_SUCCESS); }) .catch(function(err) { log.error("JWE解密失败:" + err.getMessage()); session.transfer(flowFile, REL_FAILURE); }); }
方案2:使用ExecuteCommand处理器(调用外部Node.js环境)
写独立的Node.js脚本,不依赖NiFi内置JS API,通过标准输入输出和NiFi交互,兼容性更好:
- 先在NiFi服务器上安装Node.js,执行
npm install node-jose安装依赖 - 新建独立解密脚本
/opt/nifi/scripts/decrypt-jwe.js:
const jose = require('node-jose'); let input = ''; process.stdin.on('data', chunk => input += chunk); process.stdin.on('end', async () => { try { // 替换为完整合法的JWK私钥 const privKeyJwks = { kty: "RSA", p: "aaaaaabbbccccc", q: "cddbcbvbvbmm" }; // ExecuteCommand可配置将token属性注入环境变量传入 const jweToken = process.env.TOKEN; const privKey = await jose.JWK.asKey(privKeyJwks); const decryptRes = await jose.JWE.createDecrypt(privKey).decrypt(jweToken); // 解密结果输出到标准输出,NiFi会自动捕获为输出流文件内容 process.stdout.write(decryptRes.plaintext.toString()); } catch (err) { console.error('解密失败:', err); process.exit(1); } });
- 配置ExecuteCommand处理器:
- Command Path:填node可执行文件的绝对路径
- Command Arguments:填上面脚本的绝对路径
- 配置环境变量传递属性:将流文件的
token属性映射为环境变量TOKEN
注意事项
- 你之前写的
{"p:aaaaaabbbccccc,q:cddbcbvbvbmm"}是非法对象,等价于定义了一个键为整串p:aaaaaabbbccccc,q:cddbcbvbvbmm、值为undefined的属性,必须拆分为标准键值对,同时补全JWK规范要求的所有必填字段,否则私钥解析必然失败。 - 异步操作场景下禁止在Promise回调外执行
session.transfer,否则流文件会在解密完成前被提前转移,导致属性丢失、流文件损坏。 - Java 17及以上版本已经移除Nashorn JS引擎,优先选择ExecuteCommand调用外部Node脚本的方案。
内容的提问来源于stack exchange,提问作者user19296047
相关产品推荐
相关产品推荐

