Gatsby项目使用Crypto API生成安全密码连续报错求助
你遇到的一系列报错根源是Gatsby v3+ 采用Webpack 5构建,默认不再自动注入Node.js核心模块的浏览器端polyfill。硬给Node原生模块打浏览器polyfill不仅需要安装一堆冗余依赖、容易漏配process、buffer等关联依赖,还平白增加前端包体积,完全没必要。
另外你写的密码生成函数本身还有逻辑bug:你用了crypto.randomBytes的异步回调模式,但没有等待回调返回结果就直接取外层的int变量,就算polyfill配置完全正确,拿到的也永远是undefined,生成不了有效密码。
推荐方案(零依赖、无配置、安全性最高)
如果你的密码生成逻辑跑在用户浏览器端(客户端代码),直接用浏览器原生支持的Web Crypto API即可,不需要引入任何第三方包,也不需要修改webpack配置,生成的随机数符合加密安全标准:
const generatePassword = async () => { const charSet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; const passwordLen = 12; const randomValues = new Uint32Array(passwordLen); // 调用浏览器原生加密随机数接口 crypto.getRandomValues(randomValues); return Array.from(randomValues, num => charSet[num % charSet.length]).join(""); };
这里的crypto是浏览器全局对象,不需要require导入,直接调用即可。
如果你的密码生成逻辑跑在Gatsby构建阶段/服务端(比如gatsby-node.js、getServerData接口里),直接用Node.js原生crypto模块的同步写法就行,这些代码不会被打包到前端bundle里,根本不需要配置任何polyfill:
// 仅在Node端运行的代码,不要放到客户端组件里 const crypto = require("crypto"); const generatePassword = () => { const charSet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; return Array(12) .fill(charSet) .map(str => { // 用同步方法取随机数,不要传异步回调 const randomInt = crypto.randomBytes(4).readUInt32BE(0); return str[randomInt % str.length]; }) .join(""); };
不推荐的polyfill方案(仅作排错参考)
如果你一定要在客户端代码里用crypto-browserify,需要把所有关联依赖的polyfill都配全,之前报process is not defined就是因为漏了process的注入配置:
- 先安装所有需要的依赖:
npm install crypto-browserify stream-browserify buffer process util
- 补全webpack配置:
exports.onCreateWebpackConfig = ({ stage, loaders, actions, plugins }) => { actions.setWebpackConfig({ resolve: { fallback: { crypto: require.resolve("crypto-browserify"), stream: require.resolve("stream-browserify"), buffer: require.resolve("buffer/"), util: require.resolve("util/") }, }, plugins: [ new plugins.ProvidePlugin({ process: "process/browser", Buffer: ["buffer", "Buffer"] }) ] }); };
配完之后还要修正你原来函数里的异步逻辑bug才能正常运行,这个方案会增加几百KB的前端打包体积,非必要不要用。
内容的提问来源于stack exchange,提问作者Edward

