如何将AWS Lambda集成到ALB Fargate服务并保护API端点
解决方案建议
一、不用换API Gateway——你用的HttpApi就是它的新一代产品
你提到的HttpApi本身就是AWS API Gateway的轻量版,完全支持Lambda授权器(包括自定义JWT验证的Lambda),没必要额外切换服务。直接在Api Gateway层给特定端点绑定授权器就行,比在ALB层面做更灵活。
二、CDK实现HttpApi + Lambda JWT授权器的具体步骤
1. 写JWT验证Lambda函数
这个函数要处理API Gateway的授权请求,从请求头里提取JWT令牌,验证签名、有效期、受众/发行方等关键信息。给个Python示例:
import jwt import os def lambda_handler(event, context): # 从Authorization头提取Bearer令牌 auth_header = event['headers'].get('Authorization', '') if not auth_header.startswith('Bearer '): return deny_access(event['methodArn']) token = auth_header.split(' ')[1] try: # 从环境变量取验证参数(建议用Secrets Manager存密钥,这里仅示例) decoded = jwt.decode( token, os.environ['JWT_SECRET'], algorithms=['HS256'], audience=os.environ['JWT_AUDIENCE'], issuer=os.environ['JWT_ISSUER'] ) return allow_access(decoded['sub'], event['methodArn'], decoded.get('role')) except jwt.InvalidTokenError: return deny_access(event['methodArn']) def allow_access(principal_id, method_arn, role=None): return { 'principalId': principal_id, 'policyDocument': { 'Version': '2012-10-17', 'Statement': [{ 'Action': 'execute-api:Invoke', 'Effect': 'Allow', 'Resource': method_arn }] }, 'context': {'userId': principal_id, 'role': role} } def deny_access(method_arn): return { 'principalId': 'unauthorized', 'policyDocument': { 'Version': '2012-10-17', 'Statement': [{ 'Action': 'execute-api:Invoke', 'Effect': 'Deny', 'Resource': method_arn }] } }
2. CDK里配置授权器和端点绑定
假设你已经搭好了Fargate服务和ALB,现在加Lambda授权器并绑定到/protected端点:
import * as cdk from 'aws-cdk-lib'; import * as apigatewayv2 from '@aws-cdk/aws-apigatewayv2-alpha'; import * as apigatewayv2Integrations from '@aws-cdk/aws-apigatewayv2-integrations-alpha'; import * as lambda from 'aws-cdk-lib/aws-lambda'; import * as secretsmanager from 'aws-cdk-lib/aws-secretsmanager'; export class YourApiStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props); // 已有的ALB和Fargate服务(示例,替换成你的实际构造) const alb = ...; const fargateService = ...; // 1. 从Secrets Manager取JWT密钥(建议用这个替代硬编码) const jwtSecret = secretsmanager.Secret.fromSecretNameV2(this, 'JwtSecret', 'jwt-auth-secret'); // 2. 创建JWT验证Lambda const jwtAuthLambda = new lambda.Function(this, 'JwtAuthLambda', { runtime: lambda.Runtime.PYTHON_3_11, code: lambda.Code.fromAsset('lambda/auth'), handler: 'auth.handler', environment: { JWT_SECRET: jwtSecret.secretValueFromJson('secret').toString(), JWT_AUDIENCE: 'your-api-audience', JWT_ISSUER: 'your-token-issuer' } }); // 3. 创建HttpApi的Lambda授权器 const jwtAuthorizer = new apigatewayv2.HttpLambdaAuthorizer('JwtAuthorizer', jwtAuthLambda, { identitySource: ['$request.header.Authorization'], // 指定从哪个位置取身份信息 resultsCacheTtl: cdk.Duration.minutes(5) // 缓存授权结果,减少Lambda调用次数 }); // 4. 配置ALB集成 const albIntegration = new apigatewayv2Integrations.HttpAlbIntegration('AlbIntegration', alb, { listener: alb.listeners[0], secureServerName: 'your-alb-domain.com' // 用HTTPS时需要配置 }); // 5. 创建HttpApi const httpApi = new apigatewayv2.HttpApi(this, 'ProtectedApi', { defaultIntegration: albIntegration // 未保护的端点默认走ALB }); // 6. 给/protected端点绑定授权器 httpApi.addRoutes({ path: '/protected', methods: [apigatewayv2.HttpMethod.GET, apigatewayv2.HttpMethod.POST], integration: albIntegration, authorizer: jwtAuthorizer // 这里指定该端点需要授权 }); } }
三、如果想直接在ALB层面做授权(备选)
要是不想用API Gateway,直接在ALB上挂Lambda授权器也可以:
- Lambda函数的事件格式和API Gateway不一样,要适配ALB的授权请求结构(包含
requestContext、headers等字段) - 在CDK里给ALB的监听器添加授权器,指定要保护的路径前缀(比如/protected/*)
- 注意ALB要求授权Lambda返回特定格式的响应,明确允许或拒绝请求
四、几个关键提醒
- 绝对不要硬编码JWT密钥,用Secrets Manager或Parameter Store存储,CDK里安全注入到Lambda
- 授权器的
identitySource要和你实际传令牌的方式匹配(比如Bearer令牌就在Authorization头) - 缓存授权结果能降本减延迟,但TTL别超过令牌的有效期,避免缓存过期令牌的授权结果
- 测试时一定要覆盖两种情况:有效令牌正常访问,无效/过期令牌被拒绝
内容的提问来源于stack exchange,提问作者Murat Colyaran
相关产品推荐
相关产品推荐

