在 Laravel 6、Module、Lighthouse 中实现 安全 验证 的流程(使用 @rules 指令,使用 Exists 规则)

1、当请求响应成功时的结构。如图1

图1


mutation {
  onlineStoreThemePreviewCodeGenerate(themeId: "vogue") {
    themePreviewCode
  }
}

{
  "data": {
    "onlineStoreThemePreviewCodeGenerate": {
      "themePreviewCode": "eyJpdiI6IjZlZ3RpZzlyZmp6S3BzQWJcL0N1NVR3PT0iLCJ2YWx1ZSI6IkNGdVwvdGJMZFI2MWJPRXFMbTNhdmVOUVVCVDhzb1ZnSzFNQzd2Y1RoSElGMmw4VkxOWFppbnlNbmtjaFNnbG9FXC9Oa1hYSndRU1hlcmpFMktneFNkQmVoMjhENnoxb3dQY0lxNHZnemJrNXlLTlpNKzJmbEU4RTFXNnFza2dyVG4iLCJtYWMiOiI0NzcwZjllYjIxZDliOGFkMTU2OTdiZmVmYWViN2I2OTI5NWE0ZDFjOTBmOGU1MGMyZjI3MzBjNTQxMWE3ODQ2In0="
    }
  }
}

2、但是,现阶段并未针对请求参数进行安全验证。参考:https://lighthouse-php.com/master/security/validation.html#single-arguments 。Lighthouse 允许您在查询和变更中使用 Laravel 的验证。

3、此 GraphQL API 的变更仅有一个请求参数,即 themeId,仅需要验证此字段是否在表中存在即可。

4、利用内置验证规则的最简单方法是使用 @rules 指令。使用 Exists 规则

extend type Mutation {
    "生成主题预览代码"
    onlineStoreThemePreviewCodeGenerate(themeId: ID! @rules(apply: ["exists:theme_asset,theme_id"])): OnlineStoreThemePreviewCodeGeneratePayload @field(resolver: "Modules\\ThemeStore\\Resolver\\ThemePreview\\GenerateThemePreviewCodeResolver")
}

5、测试验证规则是否有效,确定有效。如图2

图2


mutation {
  onlineStoreThemePreviewCodeGenerate(themeId: "vogue1") {
    themePreviewCode
  }
}

{
  "errors": [
    {
      "message": "Validation failed for the field [onlineStoreThemePreviewCodeGenerate].",
      "extensions": {
        "validation": {
          "themeId": [
            "The selected theme id is invalid."
          ]
        },
        "category": "validation"
      },
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "onlineStoreThemePreviewCodeGenerate"
      ],
      "trace": ...
    }
  ],
  "data": {
    "onlineStoreThemePreviewCodeGenerate": null
  }
}

6、查看 Laravel Telescope 中请求中的 SQL 语句。

select
  count(*) as aggregate
from
  `theme_asset`
where
  `theme_id` = 'vogue1'

7、但是,现阶段还存在一个问题,因为表名称的前缀恰好是 ”,如果设置为 ‘object_’,可能会有问题。再次请求,发现报错,符合预期。说明验证规则中会自动读取表前缀的。无需要调整。如图3

图3

        'mysql' => [
            ...
            'prefix' => 'object_',
        ],
{
  "errors": [
    {
      "debugMessage": "SQLSTATE[42S02]: Base table or view not found: 1146 Table 'object_store.object_theme_asset' doesn't exist (SQL: select count(*) as aggregate from `object_theme_asset` where `theme_id` = vogue1)",
      "message": "Internal server error",
      "extensions": {
        "category": "internal"
      },
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "onlineStoreThemePreviewCodeGenerate"
      ],
      "trace": [
        ...
      ]
    }
  ],
  "data": {
    "onlineStoreThemePreviewCodeGenerate": null
  }
}
永夜