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

Posted

技术标签:

【中文标题】使用无服务器框架请求验证【英文标题】:Request validation using serverless framework 【发布时间】:2018-08-14 10:56:47 【问题描述】:

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

【问题讨论】:

【参考方案1】:

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

您需要安装以下软件包:

serverless-aws-documentation serverless-reqvalidator-plugin

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

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

注意:下面只是简要介绍如何合并这些软件包。访问包的文档页面以获取更全面的示例...

    为 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
    

    告诉 API 网关实际使用模型进行验证

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

    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

【讨论】:

这有什么cmets吗?***.com/questions/54317704/…【参考方案2】:

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

【讨论】:

你如何要求 content-type 是application/json?在此示例中,如果您不提供请求正文或提供不同的内容类型,则仍会调用 Lambda。 我也遇到了同样的问题。如果内容类型与application/json 不同,仍会调用 Lambda。有没有办法将 AWS API 网关配置为只允许 application/json, content-type ? API Gateway Request Validation 建议您还不能使用默认的 Lambda-Proxies 集成正确强制执行内容类型验证。为了避免内容类型问题,您需要使用(在无服务器非默认情况下)Lambda integration 并使用“从不”作为 passThrough 行为(如果您未指定任何内容,这是默认设置)。然后,这将阻止提供的设置未定义的内容类型。 我仍然更喜欢接受的答案,因为您可以定义 OpenApi 文档以及请求验证。 我们如何验证查询字符串参数?【参考方案3】:

正如 Ivan 所说,不需要外部插件,因为无服务器框架支持。但是,我认为配置它的方式已经改变。

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

【讨论】:

NOTE: schema validators are only applied to content types you specify. Other content types are not blocked.【参考方案4】:

如果您像我一样不想按照“https://***.com/questions/49133294/request-validation-using-serverless-framework”中的建议添加插件。

如果您根据需要设置参数并希望对其进行验证,则必须将请求验证器添加到您的 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-581832806https://github.com/serverless/serverless/issues/5034#issuecomment-581832806

【讨论】:

我在尝试上述操作时收到此错误:发生错误:ApiGatewayResourceResourceDashdata - 遇到不支持的属性 RequestValidatorId。 请确保您的资源名称正确。另请参阅有关此答案的 cmets ***.com/a/61798760/5493813 @ShwetaJ 如果您觉得答案对您有帮助,请为答案投票【参考方案5】:

使用无服务器请求验证

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 

【讨论】:

以上是关于使用无服务器框架请求验证的主要内容,如果未能解决你的问题,请参考以下文章

使用 Symfony 框架在生产服务器上的用户登录失败(身份验证请求无法处理,因为...)

使用Symfony框架在生产服务器上登录失败(由于...无法处理身份验证请求)

如何在无服务器框架中包含静态文件?

无服务器框架 + AWS + Lambda + DynamoDB + GraphQL + Apollo Server = 无法使 POST 请求工作

Django框架入门

无服务器框架+ AWS + Lambda + DynamoDB + GraphQL + Apollo Server =无法使POST请求工作