如何在AWS API Gateway自定义授权器中实现未授权用户重定向(CloudFormation)
实现方案
1. 调整Lambda自定义授权器(Python)
将授权器设置为REQUEST模式(而非默认的TOKEN模式),这样可以在验证失败时返回自定义上下文信息,供后续网关响应使用。
核心逻辑代码示例
import jwt import os def lambda_handler(event, context): # 从请求头获取Bearer令牌 auth_header = event.get('headers', {}).get('Authorization') token = auth_header.split(' ')[1] if auth_header and 'Bearer' in auth_header else None # 令牌验证逻辑(替换为你的实际验证逻辑) is_valid = False try: jwt.decode(token, os.environ['SECRET_KEY'], algorithms=['HS256']) is_valid = True except: pass if is_valid: # 令牌有效,生成允许访问的策略 return { "principalId": "authenticated-user", "policyDocument": { "Version": "2012-10-17", "Statement": [ { "Action": "execute-api:Invoke", "Effect": "Allow", "Resource": event['methodArn'] } ] } } else: # 令牌无效,返回拒绝策略+重定向URL上下文 return { "principalId": "unauthenticated", "policyDocument": { "Version": "2012-10-17", "Statement": [ { "Action": "execute-api:Invoke", "Effect": "Deny", "Resource": event['methodArn'] } ] }, "context": { "redirectUrl": "https://your-login-domain.com/login" # 替换为你的登录页URL } }
2. CloudFormation中配置API Gateway网关响应
定义AWS::ApiGateway::GatewayResponse资源,覆盖默认的401 Unauthorized响应,将其改为302重定向:
AWSTemplateFormatVersion: '2010-09-09' Resources: # ... 其他资源(Lambda授权器、API Gateway RestApi等) ... # 自定义未授权响应:重定向到登录页 UnauthorizedRedirectResponse: Type: AWS::ApiGateway::GatewayResponse Properties: ResponseParameters: gatewayresponse.header.Location: "'$context.authorizer.redirectUrl'" ResponseTemplates: text/html: | <html><body>Redirecting to login page...</body></html> ResponseType: UNAUTHORIZED RestApiId: !Ref YourRestApi # 替换为你的RestApi资源名 StatusCode: '302'
3. 配置API Gateway与S3的集成
让授权通过的用户访问S3静态HTML,配置API Gateway方法集成到S3:
示例CloudFormation资源片段
# 通配资源,匹配所有子路径 StaticResource: Type: AWS::ApiGateway::Resource Properties: ParentId: !GetAtt YourRestApi.RootResourceId PathPart: "{proxy+}" RestApiId: !Ref YourRestApi # GET方法关联自定义授权器与S3集成 StaticGetMethod: Type: AWS::ApiGateway::Method Properties: AuthorizationType: CUSTOM AuthorizerId: !Ref YourCustomAuthorizer # 关联你的Lambda授权器 HttpMethod: GET Integration: IntegrationHttpMethod: GET Type: AWS Uri: !Sub "arn:aws:apigateway:${AWS::Region}:s3:path/${YourS3Bucket}/{proxy}" # 替换为你的S3桶名 Credentials: !GetAtt ApiGatewayS3AccessRole.Arn IntegrationResponses: - StatusCode: 200 ResponseParameters: method.response.header.Content-Type: integration.response.header.Content-Type RequestParameters: integration.request.path.proxy: method.request.path.proxy RequestParameters: method.request.path.proxy: true ResourceId: !Ref StaticResource RestApiId: !Ref YourRestApi MethodResponses: - StatusCode: 200 ResponseParameters: method.response.header.Content-Type: true
4. 配置必要的IAM权限
- API Gateway调用Lambda授权器的权限:
ApiGatewayAuthorizerPermission: Type: AWS::Lambda::Permission Properties: Action: lambda:InvokeFunction FunctionName: !Ref YourAuthorizerLambda # 你的授权器Lambda函数名 Principal: apigateway.amazonaws.com SourceArn: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${YourRestApi}/*/*/*"
- API Gateway读取S3桶的权限角色:
ApiGatewayS3AccessRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: apigateway.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: S3ReadAccess PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: s3:GetObject Resource: !Sub "${YourS3Bucket.Arn}/*"
关键注意事项
- 确保Lambda授权器返回的
Resource字段与API Gateway方法ARN完全匹配,避免权限范围错误。 - 登录页URL必须使用绝对路径,防止重定向出现相对路径错误。
- 修改网关响应后,需要重新部署API Gateway阶段才能生效。
内容的提问来源于stack exchange,提问作者nilskch
相关产品推荐
相关产品推荐

