使用无服务器框架请求验证

Request validation using serverless framework

我正在为后端使用无服务器框架。如何实施请求验证? (不想在 lambda 函数中编写验证)。

要使用 serverless 实现请求验证,您需要做几件事: 在堆栈中包含您的 model/header 定义,然后告诉 API 网关使用它们进行请求验证。

您需要安装以下软件包:

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

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

注意:下面只是 run-down 如何合并包的快速说明。访问包的文档页面以获取更全面的示例...

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

    您可以为您的模型导入 json 模式,并使用 serverless-aws-documentation 插件声明 http headers。 以下是将模型添加到 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 定义声明请求 headers,如下所示:

    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 包,您需要将 AWS::ApiGateway::RequestValidator 资源添加到 serverless.yml 文件中。 您可以指定是否要验证请求 body、请求 headers 或两者。

    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

现在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 部分下定义模型名称后保留它。 link to documentation

请注意,截至 2022 年 2 月,serverless-offline 插件未在您的本地验证 http.request.schemas。尽管他们支持已弃用的版本 http.request.schema.

正如 Ivan 所指出的,不需要外部插件,因为 Serverless 框架支持这一点。但是,我认为配置它的方式已经改变。

functions:
  create:
    handler: posts.create
    events:
      - http:
          path: posts/create
          method: post
          request:
            schema:
              application/json: ${file(create_request.json)}

这个例子取自: https://www.serverless.com/framework/docs/providers/aws/events/apigateway/#request-schema-validators

如果您像我一样不想按照“

如果您根据需要设置参数并想要验证它们,您必须向您的 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

提供此解决方案

使用无服务器请求验证

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