You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Qwik City中用Vercel-Edge适配器哈希密码遇部署问题求助

解决Qwik City Vercel Edge部署时argon2-browser的打包错误

问题原因

argon2-browser是为浏览器环境设计的库,它依赖Node.js内置的path模块,但Vercel Edge Runtime不支持Node.js内置模块,导致Rollup打包时出错。

解决方案

方案1:替换为兼容Edge Runtime的密码哈希库(推荐)

选择纯JS或Wasm实现、无Node内置模块依赖的argon2库,比如@noble/hashes(轻量、安全、兼容所有环境)。

步骤:

  1. 卸载argon2-browser
npm uninstall argon2-browser
  1. 安装@noble/hashes
npm install @noble/hashes
  1. 修改server$函数代码:
import { argon2id, randomBytes } from '@noble/hashes/argon2';
import { hex } from '@noble/hashes/utils';

export const authSignup = server$(async function (
  firstName: string,
  lastName: string,
  email: string,
  password: string,
  passwordConf: string,
  username: string,
) {
  // ... 你的其他验证逻辑
  const name = firstName.trim() + ' ' + lastName.trim();
  
  // 生成16字节的随机盐(不要硬编码盐,每个用户使用独立盐)
  const salt = randomBytes(16);
  // 执行argon2id哈希(推荐使用argon2id算法,平衡安全性和性能)
  const hashBytes = argon2id(password, salt, {
    timeCost: 3,      // 迭代次数
    memoryCost: 65536,// 内存占用(KB)
    parallelism: 1,   // 并行度
    length: 32        // 哈希输出长度(字节)
  });
  // 将哈希和盐转为十六进制字符串,用冒号分隔便于存储和后续验证
  const hash = `${hex(hashBytes)}:${hex(salt)}`;

  // ... 后续将用户信息和哈希存入数据库的逻辑
});

方案2:尝试配置ssr.noExternal(不推荐)

如果一定要保留argon2-browser,可以在Vite配置中标记该库不需要外部化,但由于Edge Runtime不支持path模块,大概率仍会运行失败。在vite.config.ts中添加:

export default defineConfig(() => {
  return {
    plugins: [qwikCity(), qwikVite(), vercelEdge()],
    ssr: {
      noExternal: ['argon2-browser'],
    },
  };
});

方案3:使用Web Crypto API的PBKDF2(备选)

如果不想额外安装库,可以使用Edge Runtime原生支持的Web Crypto API实现PBKDF2哈希(安全性略低于argon2,但符合标准):

export const authSignup = server$(async function (
  firstName: string,
  lastName: string,
  email: string,
  password: string,
  passwordConf: string,
  username: string,
) {
  // ... 你的其他验证逻辑
  const name = firstName.trim() + ' ' + lastName.trim();
  
  // 生成16字节随机盐
  const salt = crypto.getRandomValues(new Uint8Array(16));
  // 导入密码并生成PBKDF2哈希
  const key = await crypto.subtle.importKey(
    'raw',
    new TextEncoder().encode(password),
    { name: 'PBKDF2' },
    false,
    ['deriveBits']
  );
  const hashBuffer = await crypto.subtle.deriveBits(
    {
      name: 'PBKDF2',
      salt: salt,
      iterations: 100000, // 迭代次数,越高越安全
      hash: 'SHA-256'
    },
    key,
    256 // 哈希输出长度(256位=32字节)
  );
  // 将哈希和盐转为十六进制字符串
  const hashHex = Array.from(new Uint8Array(hashBuffer))
    .map(b => b.toString(16).padStart(2, '0'))
    .join('');
  const saltHex = Array.from(salt)
    .map(b => b.toString(16).padStart(2, '0'))
    .join('');
  const hash = `${hashHex}:${saltHex}`;

  // ... 后续存储逻辑
});

重要提示

  • 绝对不要硬编码盐(如你代码中的somesalt),必须为每个用户生成独立的随机盐,否则会严重降低密码哈希的安全性。
  • 优先选择argon2算法(如方案1),它是当前密码哈希的推荐标准,比PBKDF2、bcrypt等更安全。

内容的提问来源于stack exchange,提问作者PiWizard3852

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 14:35:37