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

如何在Node.js与Express中创建API key系统并应用于受保护路由

背景说明

我使用Node.js、Express.js、MongoDB搭建了后端系统,接入了JSON Web Token实现用户登录时生成令牌的鉴权能力,可通过令牌访问受保护路由。

当前问题

需要实现一套API Key系统并将其应用到受保护路由,目前使用Postman测试接口。

已实现的API Key校验中间件

目前已经编写了如下中间件,用于访问路由前校验API Key:

const protect = asyncHandler(async (req, res, next) => {
  if (req.header("api-key")) {
    try {
      //let api_key = req.query.api_key; // 版本1:通过查询参数传递
      //let api_key = req.params.apikey; // 版本2:通过URL路径参数传递
      let api_key = req.header("api-key"); // 版本3:通过请求头传递
      console.log(api_key);
      req.user = await User.findOne({
        apiKey: api_key,
        host: process.env.HOST,
      }).select("-password");
      if (req.user) {
        next();
      } else {
        res.status(401);
        throw new Error("未授权,API Key无效");
      }
    } catch (error) {
      res.status(401);
      throw new Error("未授权,API Key校验失败");
    }
  } else {
    res.status(401);
    throw new Error("未授权,未携带API Key");
  }
});

完整API Key系统实现方案

1. 新增API Key生成逻辑

在用户注册或用户主动申请API Key的接口中,添加生成唯一API Key的逻辑,代码示例如下:

// 引入crypto模块生成随机字符串
const crypto = require('crypto');

// 用户申请API Key的接口逻辑
const generateApiKey = asyncHandler(async (req, res) => {
  // 生成32位随机字符串作为API Key
  const apiKey = crypto.randomBytes(16).toString('hex');
  // 存入对应用户的文档中,同时记录绑定的host(如果有跨域限制需求)
  const user = await User.findByIdAndUpdate(
    req.user._id,
    { apiKey: apiKey, host: process.env.HOST },
    { new: true }
  ).select('-password');
  res.json({ apiKey: user.apiKey });
})

2. 中间件兼容双鉴权逻辑

如果需要同时支持JWT和API Key两种鉴权方式,可以修改现有中间件,优先匹配其中一种鉴权方式即可:

const protect = asyncHandler(async (req, res, next) => {
  let token;
  // 先判断有没有API Key
  if (req.header("api-key")) {
    try {
      const api_key = req.header("api-key");
      req.user = await User.findOne({
        apiKey: api_key,
        host: process.env.HOST,
      }).select("-password");
      if (req.user) return next();
      res.status(401);
      throw new Error("API Key无效");
    } catch (error) {
      res.status(401);
      throw new Error("API Key校验失败");
    }
  }
  // 没有API Key的话判断有没有JWT令牌
  else if (req.headers.authorization?.startsWith('Bearer')) {
    try {
      token = req.headers.authorization.split(' ')[1];
      const decoded = jwt.verify(token, process.env.JWT_SECRET);
      req.user = await User.findById(decoded.id).select('-password');
      next();
    } catch (error) {
      res.status(401);
      throw new Error("令牌无效");
    }
  } else {
    res.status(401);
    throw new Error("未携带鉴权信息");
  }
});

3. 路由绑定中间件

将编写好的中间件绑定到需要受保护的路由即可:

// 示例:获取用户信息接口需要鉴权
router.get('/user/profile', protect, getUserProfile)

4. Postman测试注意事项

在Postman的请求Header中添加api-key字段,值为用户生成的API Key即可完成测试,不需要额外配置其他参数。

注意:API Key属于敏感信息,请勿在前端代码中硬编码,传输时必须使用HTTPS协议避免泄露,可定期更换API Key提升安全性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 05:57:03