使用Serverless框架进行请求验证

24

我正在使用无服务器框架搭建后端。我该如何实现请求验证?(不想在 lambda 函数内编写验证逻辑)。

5个回答

36

现在,Serverless框架支持此功能,因此无需使用外部插件。

要启用请求验证,只需要将以下代码添加到serverless.yml中:

  HttpHandler:
    handler: src/lambda/http/create.handler
    events:
      - http:
          method: post
          path: items
          request:
            schemas:
              application/json: ${file(models/create-todo-model.json)}

除了直接将文件位置放在 application/json 下面,您还可以在定义模型后将其名称保存在 serverless.yml 文件的 apiGateway 部分下。 文档链接

需要注意的是:截至2022年2月,serverless-offline插件不会在本地验证http.request.schemas,尽管它们支持已弃用的版本http.request.schema


你如何要求内容类型为application/json?通过这个例子,如果你没有提供请求正文或提供了不同的内容类型,Lambda仍然会被调用。 - andrhamm
1
我也遇到了同样的问题。如果 content-type 不同于 application/json,Lambda 仍然会被调用。有没有办法配置 AWS API 网关只允许 application/json 的 content-type? - nithin
API网关请求验证建议您不能使用默认的Lambda代理集成来正确执行内容类型验证。为了避免内容类型问题,您需要使用(在无服务器非默认情况下)Lambda集成,并使用“Never”作为传递行为(如果您没有指定任何内容,则为默认值)。这将阻止未由提供的设置定义的内容类型。 - kf06925
我仍然更喜欢被接受的答案,因为你可以定义一个OpenApi文档以及请求验证。 - Filcp
我们如何验证查询字符串参数? - ShwetaJ

35

要使用serverless实现请求验证,您需要执行以下操作:

在您的堆栈中包含您的模型/标题定义,然后告诉API网关将它们用于请求验证。

您需要安装以下软件包:

然后您需要将它们包含在您的serverless.yml中:

plugins:
  - serverless-reqvalidator-plugin
  - serverless-aws-documentation

注意:以下只是快速介绍如何整合软件包。请访问软件包的文档页面以获取更全面的示例...

  1. 向API网关提供有关您的模型/标头的描述。

    您可以导入JSON模式以获取您的模型,并使用serverless-aws-documentation插件声明HTTP标头。 以下是如何将模型添加到您的serverless.yml

    custom:
      documentation:
        api:
          info:
            version: v0.0.0
            title: Some API title
            description: Some API description
        models:
          - name: SomeLambdaRequest
            contentType: application/json
            schema: ${file(models/SomeLambdaRequest.json)} # reference to your model's json schema file. You can also declare the model inline.
    

    以下是如何在 lambda 定义中引用模型:

    functions:
      someLambda:
        handler: src/someLambda.handler
        events:
          - http:
              # ... snip ...
              documentation:
                summary: some summary
                description: some description
                requestBody:
                  description: some description
                requestModels:
                  application/json: SomeLambdaRequest
    

    您也可以在Lambda函数定义中声明请求头,方法如下:

    functions:
      someLambda:
        handler: src/someLambda.handler
        events:
          - http:
              # ... snip ...
              documentation:
                summary: some summary
                description: some description
                requestHeaders:
                  - name: x-some-header
                    description: some header value
                    required: true # true or false
                  - name: x-another-header
                    description: some header value
                    required: false # true or false
    
  2. 告诉API网关实际使用模型进行验证

    此部分使用了serverless-reqvalidator-plugin包,您需要在serverless.yml文件中添加AWS::ApiGateway::RequestValidator资源。 您可以指定是否要验证请求体、请求头或两者都要验证。

  3. resources:
      Resources:
        onlyBody:
          Type: AWS::ApiGateway::RequestValidator
          Properties:
            Name: 'only-body'
            RestApiId:
              Ref: ApiGatewayRestApi
            ValidateRequestBody: true # true or false
            ValidateRequestParameters: false # true or false
    

    然后在每个单独的功能上,您可以像这样使用验证器:

    functions:
      someLambda:
        handler: src/someLambda.handler
        events:
          - http:
              # ... snip ...
              reqValidatorName: onlyBody # reference and use the 'only-body' request validator
    

把所有东西放在一起,你的 Lambda 定义看起来会像这样:

functions:
  someLambda:
    handler: src/someLambda.handler
    events:
      - http:
          # ... snip ...
          reqValidatorName: onlyBody # reference and use the 'only-body' request validator
          documentation:
            summary: some summary
            description: some description
            requestBody:
              description: some description
            requestModels:
              application/json: SomeLambdaRequest
            requestHeaders:
              - name: x-some-header
                description: some header value
                required: true # true or false
              - name: x-another-header
                description: some header value
                required: false # true or false

你对这个有什么评论吗?https://stackoverflow.com/questions/54317704/how-to-do-serverless-binary-configuration-right - fodon

3

注意:模式验证器仅适用于您指定的内容类型。其他内容类型不会被阻止。 - Zacbe Gonzalez
应该是schemas,而不是schema - Bersan

2

如果你和我一样,不想像"https://dev59.com/F1UM5IYBdhLWcg3wOeTz"中建议的那样添加插件。

如果你设置了必需参数并且想要验证它们,你必须在serverless.yml中添加请求验证器。

Resources:
  ParameterRequestValidator:
    Type: AWS::ApiGateway::RequestValidator
    Properties:
      Name: ParameterRequestValidator
      RestApiId:
        Ref: ApiGatewayRestApi
      ValidateRequestBody: false
      ValidateRequestParameters: true

  ApiGatewayMethodNameOfYourApiLookItUpInYourTemplate:
    Properties:
      RequestValidatorId:
        Ref: ParameterRequestValidator

您想要验证的方法将被命名为ApiGateway<Method><Get | Post | Patch | Put | Delete >。您可以在创建模板文件时查找该名称。
感谢https://github.com/serverless/serverless/issues/5034#issuecomment-581832806提供此解决方案。

尝试上述操作时,我遇到了以下错误:发生错误:ApiGatewayResourceResourceDashdata - 遇到不支持的属性RequestValidatorId。 - ShwetaJ
1
请确保您的资源名称正确。还请参阅有关此问题的评论以获取更多详细信息 https://dev59.com/yKnka4cB1Zd3GeqPOnmk#61798760 - st.huber
@ShwetaJ 如果你觉得这些答案对你有帮助,请点赞。 - st.huber

-1

使用无服务器进行请求验证

plugins:
  - serverless-python-requirements
  - serverless-wsgi
  - serverless-reqvalidator-plugin
  - serverless-aws-documentation
  
provider:
  name: aws
  runtime: python3.8
  region: us-east-1

functions:
  hello:
    handler: handler.hello
    events:
      - http:
          path: /
          method: get
  likes:
    handler: handler.likes
    events:
      - http:
          path: /likes
          method: get
          integration: lambda
          reqValidatorName: xMyRequestValidator
          request:
            passThrough: NEVER
            parameters:
              querystrings:
                userid: true
                activityid: true
            template:
              application/json: '{ "userid":"$input.params(''userid'')","activityid":"$input.params(''activityid'')"}'
          response:
            headers:
              Content-Type: "'application/json'"

custom:
  wsgi:
    app: handler.app
    pythonBin: python # Some systems with Python3 may require this
    packRequirements: false
  pythonRequirements:
    dockerizePip: non-linux
resources:
  Resources:
    xMyRequestValidator:  
      Type: "AWS::ApiGateway::RequestValidator"
      Properties:
        Name: 'my-req-validator'
        RestApiId: 
          Ref: ApiGatewayRestApi
        ValidateRequestBody: true
        ValidateRequestParameters: true 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接