Serverless框架下AWS Lambda自定义授权器获取源IP及前置通用逻辑实现
嘿,这个问题我之前也碰到过,给你几个实用的解决方案,按优先级排序:
1. 先确认:Custom Authorizer其实能拿到源IP!
你可能没注意到,在AWS REST API的TOKEN类型Custom Authorizer中,事件对象里是包含请求源IP的,路径是event.requestContext.identity.sourceIp。
举个例子,你的Authorizer代码里可以直接这么写:
exports.handler = async (event) => { const token = event.authorizationToken; const sourceIp = event.requestContext.identity.sourceIp; // 1. 解析令牌,取出里面的IP/CIDR限制规则 const decodedToken = verifyToken(token); const allowedIps = decodedToken.allowedIps || []; // 2. 验证当前请求IP是否在允许列表内 const isIpAllowed = checkIpAgainstRules(sourceIp, allowedIps); if (!isIpAllowed) { return generatePolicy('user', 'Deny', event.methodArn); } // 验证通过,返回允许策略 return generatePolicy('user', 'Allow', event.methodArn); };
如果这个方法可行,那这是最贴合你现有架构的方案,不用额外改动Lambda函数,直接在Authorizer里完成所有验证。
2. 用Lambda Layer封装通用IP验证逻辑
如果因为某些场景(比如用的是HTTP API,或者Authorizer无法访问令牌里的IP规则存储)导致Authorizer拿不到IP/无法验证,那Lambda Layer是最简洁的通用逻辑复用方案:
第一步:封装验证逻辑到Layer
写一个独立的IP验证模块,比如ip-validator.js,打包成Lambda Layer:const cidrTools = require('cidr-tools'); exports.validateIp = (allowedIps, sourceIp) => { const isAllowed = allowedIps.some(rule => { if (rule.includes('/')) { // 处理CIDR网段 return cidrTools.contains(rule, sourceIp); } else { // 处理单个IP return rule === sourceIp; } }); if (!isAllowed) { throw new Error('请求IP不在允许范围内'); } };第二步:在Serverless配置中引入Layer
给所有需要验证的Lambda函数添加Layer引用:service: my-api-service functions: getResource: handler: handlers/getResource.main layers: - arn:aws:lambda:us-east-1:你的账号ID:layer:IpValidator:1 events: - http: path: resource/{id} method: get authorizer: customAuthorizer # 其他Lambda函数同理第三步:在Lambda handler中调用验证
每个Lambda的handler开头先执行IP验证,不通过直接返回403:const { validateIp } = require('/opt/ip-validator'); exports.main = async (event) => { try { // 从请求上下文拿源IP和Authorizer传递的令牌Claims const sourceIp = event.requestContext.identity.sourceIp; const allowedIps = event.requestContext.authorizer.allowedIps; // 执行IP验证 validateIp(allowedIps, sourceIp); // 正常业务逻辑 return { statusCode: 200, body: JSON.stringify('操作成功') }; } catch (err) { return { statusCode: 403, body: JSON.stringify(err.message) }; } };
3. 进阶:用Serverless插件自动注入前置逻辑
如果你的服务有很多Lambda函数,不想手动在每个handler里写验证调用,可以写一个简单的Serverless插件,在打包阶段自动给所有handler注入IP验证的代码。不过这个需要一点插件开发能力,适合大规模服务场景。
内容的提问来源于stack exchange,提问作者Prasanth
相关产品推荐
相关产品推荐

