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

EC2上Node.js Express后端如何通过Cognito实现移动端用户认证访问控制

实现已认证用户访问EC2上Express接口的方案

这个问题问得好!既然你已经用Cognito搞定了客户端认证,那咱们可以在Express里加一个JWT验证中间件,实现类似Lambda IAM认证的效果——核心就是校验客户端传来的Cognito令牌合法性,只有通过校验的请求才能访问你的CRUD接口。下面是针对你的EC2架构的具体实现步骤:

核心思路

用户通过Cognito客户端SDK获取到ID Token(推荐用于身份校验)或Access Token(多用于API授权)后,在请求Express接口时将令牌放在Authorization请求头中(格式为Bearer <token>)。Express的自定义中间件会负责:

  1. 提取请求头中的令牌
  2. 验证令牌的签名、过期时间、受众(Audience)和颁发者(Issuer)
  3. 校验通过后,将解析后的用户信息挂载到请求对象上,放行到后续的CRUD接口;校验失败则返回401未授权。

具体实现步骤

1. 准备Cognito配置信息

先确认你的Cognito用户池和客户端配置正确,并且客户端能正常获取令牌。记录下以下信息(后续会用到):

  • AWS区域(比如us-east-1)
  • 用户池ID(格式类似us-east-1_XXXXXXXXX)
  • 应用客户端ID(一串随机字符串)

2. 安装依赖包

在你的Express项目中,安装用于JWT解析和公钥获取的依赖:

npm install jsonwebtoken jwks-rsa
  • jsonwebtoken:负责解析和验证JWT令牌
  • jwks-rsa:从Cognito的公钥端点获取用于验证签名的公钥(避免硬编码公钥,适配Cognito自动轮换密钥的机制)

3. 编写JWT验证中间件

创建一个中间件文件(比如middleware/authenticate.js),实现令牌校验逻辑:

const jwt = require('jsonwebtoken');
const jwksClient = require('jwks-rsa');

// 初始化JWKS客户端,指向Cognito的公钥端点
const client = jwksClient({
  jwksUri: `https://cognito-idp.${process.env.AWS_REGION}.amazonaws.com/${process.env.COGNITO_USER_POOL_ID}/.well-known/jwks.json`
});

// 根据令牌头中的kid获取对应的公钥
function getSigningKey(header, callback) {
  client.getSigningKey(header.kid, (err, key) => {
    const signingKey = key.publicKey || key.rsaPublicKey;
    callback(null, signingKey);
  });
}

// 核心认证中间件
const authenticate = (req, res, next) => {
  // 从请求头提取令牌
  const authHeader = req.headers.authorization;
  if (!authHeader || !authHeader.startsWith('Bearer ')) {
    return res.status(401).json({ message: '请提供有效的身份令牌' });
  }

  const token = authHeader.split(' ')[1];

  // 验证JWT的合法性
  jwt.verify(token, getSigningKey, {
    audience: process.env.COGNITO_APP_CLIENT_ID, // 必须匹配你的Cognito客户端ID
    issuer: `https://cognito-idp.${process.env.AWS_REGION}.amazonaws.com/${process.env.COGNITO_USER_POOL_ID}`, // 必须匹配用户池的颁发者地址
    algorithms: ['RS256'] // Cognito用RS256算法签名JWT
  }, (err, decodedToken) => {
    if (err) {
      return res.status(401).json({ message: '令牌无效或已过期' });
    }
    // 将解析后的用户信息挂载到req对象,后续接口可直接使用
    req.user = decodedToken;
    next();
  });
};

module.exports = authenticate;

4. 在受保护的路由上使用中间件

把上面的中间件添加到需要保护的CRUD路由前,只有通过认证的请求才能访问这些接口:

const express = require('express');
const router = express.Router();
const authenticate = require('./middleware/authenticate');
// 假设你有一个操作RDS的控制器
const rdsController = require('./controllers/rdsController');

// 受保护的查询接口
router.get('/api/items', authenticate, rdsController.getItems);

// 受保护的创建接口
router.post('/api/items', authenticate, rdsController.createItem);

// 受保护的更新接口
router.put('/api/items/:id', authenticate, rdsController.updateItem);

// 受保护的删除接口
router.delete('/api/items/:id', authenticate, rdsController.deleteItem);

module.exports = router;

5. 配置环境变量

为了避免硬编码敏感信息,把Cognito相关配置放在环境变量中:

  • 你可以在EC2实例上直接设置环境变量,或者用dotenv包加载.env文件:
    AWS_REGION=us-east-1
    COGNITO_USER_POOL_ID=us-east-1_XXXXXXXXX
    COGNITO_APP_CLIENT_ID=xxxxxxxxxxxxxxxxxxxxxxxxxx
    
    如果用dotenv,记得在项目入口文件(比如app.js)顶部添加:
    require('dotenv').config();
    

6. 额外安全建议

  • 强制HTTPS:确保你的Express后端只通过HTTPS提供服务,防止令牌在传输过程中被窃取
  • 权限细化:可以通过Cognito令牌中的cognito:groups字段实现角色权限控制(比如区分管理员和普通用户)
  • 令牌刷新:实现Cognito令牌的刷新机制,避免用户因令牌过期频繁重新登录
  • 日志监控:添加认证失败的日志记录,方便排查身份验证相关问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:43:15