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

基于NodeJS+JWT的双角色(用户/代理)认证授权机制设计建议

区分用户/代理角色并实现JWT权限校验方案

1. 在JWT Payload中嵌入角色标识

生成JWT时,直接把角色类型(user或agent)写入payload,代理账号额外添加managedUserIds字段,存储其负责的用户ID列表。示例代码:

// 生成普通用户令牌
function generateUserToken(user) {
  return jwt.sign(
    {
      id: user.id,
      role: 'user',
      email: user.email
    },
    process.env.JWT_SECRET,
    { expiresIn: '24h' }
  );
}

// 生成代理用户令牌
function generateAgentToken(agent) {
  return jwt.sign(
    {
      id: agent.id,
      role: 'agent',
      email: agent.email,
      managedUserIds: agent.managedUserIds // 代理管辖的用户ID数组
    },
    process.env.JWT_SECRET,
    { expiresIn: '24h' }
  );
}

2. 编写分层的权限校验中间件

先做通用认证解析JWT,再按角色拆分专属校验逻辑:

// 通用JWT解析中间件
const authenticate = (req, res, next) => {
  const token = req.headers.authorization?.split(' ')[1];
  if (!token) {
    return res.status(401).json({ message: '未提供有效令牌' });
  }

  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    req.user = decoded;
    next();
  } catch (err) {
    return res.status(403).json({ message: '令牌无效或已过期' });
  }
};

// 校验仅普通用户可访问
const requireUserRole = (req, res, next) => {
  if (req.user.role !== 'user') {
    return res.status(403).json({ message: '仅普通用户可执行此操作' });
  }
  next();
};

// 校验仅代理可访问
const requireAgentRole = (req, res, next) => {
  if (req.user.role !== 'agent') {
    return res.status(403).json({ message: '仅代理可执行此操作' });
  }
  next();
};

3. 代理代操作的额外权限校验

代理代用户执行操作时,需要验证其是否有权限操作目标用户,可单独写中间件:

// 校验代理是否有权操作指定用户
const requireAgentForTargetUser = (req, res, next) => {
  const targetUserId = req.body.targetUserId || req.params.targetUserId;
  if (!targetUserId) {
    return res.status(400).json({ message: '需指定目标用户ID' });
  }

  if (!req.user.managedUserIds.includes(targetUserId)) {
    return res.status(403).json({ message: '你无权操作该用户' });
  }
  next();
};

4. 路由层的实际使用示例

// 普通用户自行租车接口
app.post('/api/car/rent', authenticate, requireUserRole, (req, res) => {
  // 业务逻辑:用req.user.id作为租车人ID
  res.json({ message: '租车申请提交成功', userId: req.user.id });
});

// 代理代用户租车接口
app.post('/api/agent/car/rent', authenticate, requireAgentRole, requireAgentForTargetUser, (req, res) => {
  // 业务逻辑:用req.body.targetUserId作为实际租车人ID
  res.json({ 
    message: '代用户提交租车申请成功', 
    targetUserId: req.body.targetUserId,
    agentId: req.user.id 
  });
});

5. 注意事项

  • 如果代理负责的用户列表频繁变动,建议不要把managedUserIds存在JWT里,而是在校验时实时查询数据库,避免令牌过期前权限不一致
  • JWT payload只存必要的非敏感数据,不要放密码、手机号等隐私信息
  • 权限校验逻辑尽量封装在中间件,减少业务代码里的重复校验

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 08:17:09