跳到主要内容

Web3 角色权限管理系统

系统概述

基于 Solidity 智能合约的角色权限管理系统。该系统通过 Web Dashboard 和后端服务实现超级管理员(super admin)对运营管理员的完整生命周期管理:包括新建账号、自动生成关联钱包、链上授权、日常操作代理签名,以及离职时的权限撤销和账号删除。

核心目标

  • 实现运营管理员的无感钱包管理(无需自行保管私钥)。
  • 确保 Dashboard 操作通过具有对应权限的链上地址执行,实现可追溯性。
  • 覆盖管理员从入职到离职的全流程自动化与安全控制。
  • 降低私钥管理风险,防止未授权操作。

前提假设

  • 智能合约采用基于角色的访问控制(RBAC),推荐使用 OpenZeppelin 的 AccessControl 库(例如 ADMIN_ROLE、OPERATOR_ROLE 等角色)。
  • 后端使用 Node.js + ethers.js(或 web3.js)与以太坊兼容链交互。
  • Dashboard 为 Web 应用(例如 React),支持用户名/密码登录。
  • 项目运行在以太坊主网或兼容链上。
  • 超级管理员拥有合约部署权限及其钱包地址已被设为 DEFAULT_ADMIN_ROLE。

系统架构

主要组件

  1. Dashboard(前端)

    • 超级管理员创建/删除运营账号的界面。
    • 运营管理员执行合约操作的界面(如参数调整、暂停合约等)。
    • 负责用户名/密码认证及会话管理。
  2. 后端服务(Backend)

    • 处理 Dashboard 的 API 请求。
    • 管理用户数据库(用户名、密码哈希、关联钱包地址)。
    • 负责生成以太坊钱包(公私钥对)。
    • 使用存储的私钥代理签名并调用合约。
    • 与区块链 RPC 节点交互(推荐 Infura/Alchemy)。
  3. 数据库

    • 存储用户凭证、钱包关联关系、审计日志。
    • 推荐 PostgreSQL 或 MongoDB,敏感字段需加密存储。
  4. Solidity 智能合约

    • 实现 RBAC,支持 grantRole / revokeRole 方法。
    • 关键功能添加 onlyRole 修饰符限制调用者。
    • 由超级管理员部署并初始化。
  5. 区块链节点提供商

    • 提供 RPC 接口,用于交易广播和合约查询。

数据流概览

  • 账号创建:Dashboard → 后端(生成钱包 → 存储关联 → 超级管理员钱包调用合约授权)。
  • 日常操作:Dashboard → 后端(验证身份 → 使用关联钱包签名 → 调用合约)。
  • 账号删除:Dashboard → 后端(超级管理员钱包调用合约撤销权限 → 删除数据库记录)。

管理员生命周期流程

1. 新管理员入职(招聘)

  • 触发:超级管理员在 Dashboard 创建新账号(用户名:admin1,密码:xxx)。

  • 详细步骤:

    1. Dashboard 调用后端 API:POST /users 携带 {username, password}
    2. 后端校验用户名唯一性。
    3. 后端生成新以太坊钱包(例如 ethers.Wallet.createRandom()),得到地址 0xAA... 和私钥。
    4. 后端将数据存入数据库:{username, hashed_password, wallet_address, encrypted_private_key}
    5. 后端使用超级管理员钱包向 0xAA... 转账 m 个 Gas 代币
    • m 可配置(建议初始值 0.5~2 个主网代币,根据链上 Gas 价格和预期操作频率调整)。
    • 转账交易由超级管理员钱包签名并广播。
    • 等待交易确认。
    • 记录转账交易哈希到数据库和审计日志(字段:gas_transfer_out_tx)。
    1. 后端使用超级管理员钱包签名,调用合约 grantRole(OPERATOR_ROLE, 0xAA...)。
    2. 等待交易上链确认。
    3. 返回成功响应给 Dashboard(仅显示用户名和地址,显示钱包地址、初始 Gas 余额、转账交易哈希, 不暴露私钥)。
  • 异常处理:

    • 交易失败:重试或通知超级管理员。
    • 用户名重复:拒绝创建。
    • 钱包生成失败:记录日志并重试。
    • Gas 转账失败:回滚整个创建流程(不存储用户记录、不授权),通知超级管理员检查余额或网络。
    • 授权交易失败:已转账的 Gas 暂时滞留,可手动归集或重试授权。
    • 建议:将 Gas 转账放在授权之前,确保即使授权失败也能手动回收。

2. 管理员日常操作

  • 触发:运营管理员登录 Dashboard 并点击某合约操作按钮。

  • 详细步骤:

    1. Dashboard 验证会话有效性。
    2. Dashboard 调用后端 API(如 POST /operations/updateParam)并传递参数。
    3. 后端根据会话获取用户记录及关联钱包。
    4. 后端解密私钥,构造签名者(new ethers.Wallet(privateKey, provider))。
    5. 后端调用合约对应方法并签名交易。
    6. 广播交易并监控结果。
    7. 将交易哈希或结果返回给 Dashboard。
    8. 可选补充:在运营管理员执行合约操作前,后端可检查关联地址 Gas 余额。
    9. 如果余额低于阈值(例如 < 0.1 个代币),自动从超级管理员钱包补充一定数量 Gas。
    10. 补充交易记录到日志(gas_top_up_tx)。
  • 异常处理:

    • 会话失效:跳转登录页。
    • 链上权限不足:返回错误(理论上不应发生)。
    • Gas 费用过高:预估 Gas 并可让用户确认。

3. 管理员离职(删除账号)

  • 触发:超级管理员在 Dashboard 删除某账号。

  • 详细步骤:

    1. Dashboard 调用后端 API:DELETE /users/admin1。
    2. 后端验证操作人为超级管理员。
    3. 查询该用户关联的钱包地址。
    4. 归集剩余 Gas 代币
      1. 后端解密该钱包私钥。
      2. 查询 0xAA... 当前原生代币余额。
      3. 如果余额 > 最小保留值(例如 0.01 个代币,用于防止尘埃攻击),则构造转账交易:
        1. 发送方:0xAA...(使用其私钥签名)。
        2. 接收方:超级管理员指定的资金池地址(可配置为超级管理员钱包或专用归集地址)。
        3. 金额:balance - 保留值(或全部发送,设置高 Gas Limit 确保成功)。
      4. 广播归集交易,等待确认。
      5. 记录归集交易哈希(gas_collect_tx)。
    5. 后端使用超级管理员钱包签名,调用合约 revokeRole(OPERATOR_ROLE, 0xAA...)。
    6. 等待交易确认成功后,再删除数据库记录(含加密私钥)。
    7. 返回成功响应。
  • 异常处理:

    • 撤销交易失败:不删除数据库记录,避免链上残留权限。
    • 存在活跃会话:强制失效该用户所有会话。

安全注意事项

  • 私钥管理

    • 私钥绝不在前端或日志中暴露。
    • 数据库中私钥必须加密存储(推荐 AES + 主密钥存放于环境变量或秘密管理服务,如 AWS Secrets Manager)。
    • 生产环境建议使用 HSM(硬件安全模块)避免软件明文存储。
    • 风险点:后端被攻破可能导致所有私钥泄露,需严格控制服务器访问权限。
  • 配置化 Gas 管理

    • 在后端配置文件或数据库中设置:
      • 初始转账金额 initial_gas_amount
      • 低余额补充阈值 low_balance_threshold
      • 补充金额 top_up_amount
      • 归集保留最小值 min_reserve_balance
      • 归集目标地址 collect_to_address
  • 身份认证

    • 密码使用强哈希算法(bcrypt 或 Argon2)。
    • 采用 JWT 或 Session + 短过期时间。
    • 登录接口增加速率限制防暴力破解。
    • 建议开启 2FA(双因素认证)。
  • 合约安全

    • grantRole / revokeRole 必须限制为 onlyRole(DEFAULT_ADMIN_ROLE)。
    • 合约需经过专业审计,防范重入等常见漏洞。
    • 生产环境超级管理员操作建议升级为多签钱包(Gnosis Safe)。
  • 审计日志

    • 记录所有关键操作(创建、删除、链上调用),包含操作人、时间、交易哈希。
    • 日志建议使用不可篡改存储(如追加式数据库或链上事件)。
  • 其他风险

    • 钓鱼攻击:管理员需注意 Dashboard 域名安全。
    • 私钥轮换:建议定期为活跃管理员重新生成钱包并更新权限。
    • 合规性:根据项目所在辖区,可能需要对管理员进行 KYC。

实现技术建议(伪代码)

// 创建用户 - Gas 转账 + 授权
const wallet = ethers.Wallet.createRandom();
const address = wallet.address;

// 存储加密私钥...

// Step 1: 转账 Gas
const superSigner = new ethers.Wallet(process.env.SUPER_ADMIN_PK, provider);
const gasAmount = ethers.parseEther("1.0"); // 可配置 m 个
const transferTx = await superSigner.sendTransaction({
to: address,
value: gasAmount,
});
await transferTx.wait();
console.log("Gas transfer tx:", transferTx.hash);

// Step 2: 授权角色
const contract = new ethers.Contract(CONTRACT_ADDR, ABI, superSigner);
const grantTx = await contract.grantRole(OPERATOR_ROLE, address);
await grantTx.wait();

// 删除用户 - 归集 + 撤销
const userWallet = new ethers.Wallet(decryptedPrivateKey, provider);
const balance = await provider.getBalance(address);

if (balance > ethers.parseEther("0.01")) {
const collectTx = await userWallet.sendTransaction({
to: process.env.COLLECT_ADDRESS,
value: balance - ethers.parseEther("0.005"), // 保留一点 Gas 给交易本身
gasLimit: 21000,
gasPrice: await provider.getGasPrice(),
});
await collectTx.wait();
}

// 撤销角色(superSigner)
const revokeTx = await contract.revokeRole(OPERATOR_ROLE, address);
await revokeTx.wait();

// 最后删除 DB 记录