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

如何让API Gateway验证HTTP查询字符串参数的取值规则?

问题描述

我正尝试让API Gateway验证HTTP查询字符串参数的取值规则。通过配置绑定Content-Type为application/x-www-form-urlencoded的AWS::ApiGateway::Model资源,我将唯一的message参数限制为只能取foo或bar值。目前APIGW可以验证message参数是否存在:

curl -H "Content-Type: application/x-www-form-urlencoded"  "https://xxxxxxxxxx.execute-api.eu-west-1.amazonaws.com/1-0-0/hello?messag=foo"
{"message": "Missing required request parameters: [message]"}

但无法验证或限制参数的取值,例如传入whatever时仍能通过:

curl -H "Content-Type: application/x-www-form-urlencoded"  "https://xxxxxxxxxx.execute-api.eu-west-1.amazonaws.com/1-0-0/hello?message=whatever"
you sent 'whatever'

请问我哪里配置出错了?


我的CloudFormation模板
AWSTemplateFormatVersion: '2010-09-09'
Outputs:
  PublicApiEndpoint:
    Value:
      Fn::Sub: https://${PublicApiRestApi}.execute-api.${AWS::Region}.${AWS::URLSuffix}/${PublicApiStage}
Parameters:
  MemorySizeDefault:
    Default: '512'
    Type: String
  RuntimeVersion:
    Default: '3.8'
    Type: String
  TimeoutDefault:
    Default: '5'
    Type: String
Resources:
  HelloFunction:
    Properties:
      Code:
        ZipFile: |
          def handler(event, context):
              message=event["queryStringParameters"]["message"]
              response="you sent '%s'" % message
              return {'statusCode': 200,
                      'headers': {"Content-Type": "text/plain"},
                      'body': response}
      Handler: index.handler
      MemorySize:
        Ref: MemorySizeDefault
      Role:
        Fn::GetAtt:
        - HelloFunctionRole
        - Arn
      Runtime:
        Fn::Sub: python${RuntimeVersion}
      Timeout:
        Ref: TimeoutDefault
    Type: AWS::Lambda::Function
  HelloFunctionRole:
    Properties:
      AssumeRolePolicyDocument:
        Statement:
        - Action: sts:AssumeRole
          Effect: Allow
          Principal:
            Service: lambda.amazonaws.com
        Version: '2012-10-17'
      Policies:
      - PolicyDocument:
          Statement:
          - Action:
            - logs:CreateLogGroup
            - logs:CreateLogStream
            - logs:PutLogEvents
            Effect: Allow
            Resource: '*'
          Version: '2012-10-17'
        PolicyName:
          Fn::Sub: hello-function-role-policy-${AWS::StackName}
    Type: AWS::IAM::Role
  HelloEndpointMethod:
    Properties:
      AuthorizationType: NONE
      HttpMethod: GET
      Integration:
        IntegrationHttpMethod: POST
        Type: AWS_PROXY
        Uri:
          Fn::Sub:
          - arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${arn}/invocations
          - arn:
              Fn::GetAtt:
              - HelloFunction
              - Arn
      RequestParameters:
        "method.request.querystring.message": true
      RequestValidatorId:
        Ref: HelloEndpointValidator
      RequestModels:
        "application/x-www-form-urlencoded": HelloEndpointModel
      ResourceId:
        Ref: HelloEndpointResource
      RestApiId:
        Ref: PublicApiRestApi
    Type: AWS::ApiGateway::Method
  HelloEndpointPermission:
    Properties:
      Action: lambda:InvokeFunction
      FunctionName:
        Ref: HelloFunction
      Principal: apigateway.amazonaws.com
      SourceArn:
        Fn::Sub: arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${PublicApiRestApi}/${PublicApiStage}/GET/hello
    Type: AWS::Lambda::Permission
  HelloEndpointResource:
    Properties:
      ParentId:
        Fn::GetAtt:
        - PublicApiRestApi
        - RootResourceId
      PathPart: hello
      RestApiId:
        Ref: PublicApiRestApi
    Type: AWS::ApiGateway::Resource
  HelloEndpointValidator:
    Properties:
      RestApiId:
        Ref: PublicApiRestApi
      ValidateRequestParameters: true
    Type: AWS::ApiGateway::RequestValidator
  HelloEndpointModel:
    Properties:
      RestApiId:
        Ref: PublicApiRestApi
      ContentType: 'application/x-www-form-urlencoded'
      Name: HelloEndpointModel
      Schema:
        "$schema": "http://json-schema.org/draft-04/schema#"
        type: object
        properties:
          message:
            type: string
            pattern: "^((foo)|(bar))$"
        required:
          - message
    Type: AWS::ApiGateway::Model    
  PublicApiDeployment:
    DependsOn:
    - HelloEndpointMethod
    Properties:
      RestApiId:
        Ref: PublicApiRestApi
    Type: AWS::ApiGateway::Deployment
  PublicApiRestApi:
    Properties:
      Name:
        Fn::Sub: public-api-rest-api-${AWS::StackName}
    Type: AWS::ApiGateway::RestApi
  PublicApiStage:
    Properties:
      DeploymentId:
        Ref: PublicApiDeployment
      RestApiId:
        Ref: PublicApiRestApi
      StageName: 1-0-0
    Type: AWS::ApiGateway::Stage

问题分析与解决

你的配置有两个核心问题:

  1. RequestValidator仅校验参数存在性,不处理取值规则
    你当前的HelloEndpointValidator只开启了ValidateRequestParameters: true,这个配置仅会检查RequestParameters中指定的参数是否存在,不会对参数的取值做校验——取值规则校验需要RequestModels配合ValidateRequestBody实现,但这里存在关键限制。

  2. GET查询字符串无法通过application/x-www-form-urlencoded的Model校验
    API Gateway中,RequestModels绑定的Content-Type仅作用于请求体(RequestBody),而GET请求的查询字符串不属于请求体范畴。你指定的application/x-www-form-urlencoded类型对应的是POST/PUT等请求的表单请求体,GET的查询参数不会被解析到这个Model对应的结构中,因此无法触发取值校验。

解决办法

要校验GET查询参数的取值,可选择以下两种方案:

方案一:使用Lambda授权器前置校验

在请求到达业务Lambda前,通过自定义授权器校验message的取值:

  • 创建Lambda授权器函数,检查event.queryStringParameters.message是否为foo或bar,不符合则返回拒绝策略
  • 修改HelloEndpointMethod的AuthorizationType为CUSTOM,并关联该授权器
  • 确保授权器拥有API Gateway调用权限

方案二:在业务Lambda中直接校验

利用AWS_PROXY集成的透传特性,在业务逻辑开头加入校验:

def handler(event, context):
    message = event["queryStringParameters"]["message"]
    if message not in ["foo", "bar"]:
        return {
            'statusCode': 400,
            'headers': {"Content-Type": "application/json"},
            'body': '{"error": "message must be foo or bar"}'
        }
    response = "you sent '%s'" % message
    return {'statusCode': 200,
            'headers': {"Content-Type": "text/plain"},
            'body': response}

补充说明

如果一定要用API Gateway原生Model校验,需将参数放到POST请求的表单体中,同时修改HelloEndpointMethod的HttpMethod为POST,开启ValidateRequestBody: true的RequestValidator,这样Model的pattern规则才会生效。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 01:50:24