Help us learn about your current experience with the documentation. Take the survey.

REST API 垃圾信息防护和 CAPTCHA 支持

如果模型可以通过 REST API 进行修改,你还必须为所有可能修改可被垃圾信息攻击或与垃圾信息相关属性的 API 端点添加支持。这肯定包括 POSTPUT 变更操作,但也可能包括其他操作,例如那些与更改模型的机密/公开标志相关的操作。

为 REST 端点添加支持

主要步骤如下:

  1. 在你的 resource 中添加 helpers SpammableActions::CaptchaCheck::RestApiActionsSupport

  2. 向更新服务类构造函数传递 perform_spam_check: true。 在创建服务中,它默认设置为 true

  3. 创建或更新 Spammable 模型实例后,调用 #check_spam_action_response!, 将创建或更新的实例保存在变量中。

  4. 识别请求 failure 情况的错误处理逻辑, 当创建或更新不成功时。这些表示可能的垃圾信息检测, 这会在 Spammable 实例中添加错误。 错误通常类似于 render_api_error!render_validation_error!

  5. 将现有的错误处理逻辑包装在 with_captcha_check_rest_api(spammable: my_spammable_instance) 调用中, 将你保存在变量中的 Spammable 模型实例作为 spammable: 命名参数传递。此调用将:

    1. 对模型执行必要的垃圾信息检查。
    2. 如果检测到垃圾信息:
      • 抛出一个带有描述性垃圾信息特定错误消息的 Grape #error! 异常。
      • 将相关信息作为错误字段添加到响应中。 有关这些字段的更多详细信息,请参阅 REST API 文档中 解决被检测为垃圾信息的请求 的部分。

    如果你使用上面描述的标准 ApolloLink 或 Axios 拦截器 CAPTCHA 支持, 你可以忽略字段细节,因为它们会被自动处理。 如果你尝试直接使用 GraphQL API 来处理失败的潜在垃圾信息检查, 并使用已解决的 CAPTCHA 响应重新提交请求,这些字段就会变得相关。

以下是 snippets 资源上 postput 操作的示例:

module API
  class Snippets < ::API::Base
    #...
    resource :snippets do
      # 这个辅助方法提供 `#with_captcha_check_rest_api`
      helpers SpammableActions::CaptchaCheck::RestApiActionsSupport

      post do
        #...
        service_response = ::Snippets::CreateService.new(project: nil, current_user: current_user, params: attrs).execute
        snippet = service_response.payload[:snippet]

        if service_response.success?
          present snippet, with: Entities::PersonalSnippet, current_user: current_user
        else
          # 将常规错误响应包装在 `with_captcha_check_rest_api(spammable: snippet)` 块中
          with_captcha_check_rest_api(spammable: snippet) do
            # 如果检测到可能的垃圾信息,`#with_captcha_check_rest_api` 会抛出异常
            # 让 Grape 通过 `error!` 处理
            render_api_error!({ error: service_response.message }, service_response.http_status)
          end
        end
      end

      put ':id' do
        #...
        service_response = ::Snippets::UpdateService.new(project: nil, current_user: current_user, params: attrs, perform_spam_check: true).execute(snippet)

        snippet = service_response.payload[:snippet]

        if service_response.success?
          present snippet, with: Entities::PersonalSnippet, current_user: current_user
        else
          # 将常规错误响应包装在 `with_captcha_check_rest_api(spammable: snippet)` 块中
          with_captcha_check_rest_api(spammable: snippet) do
            # 如果检测到可能的垃圾信息,`#with_captcha_check_rest_api` 会抛出异常
            # 让 Grape 通过 `error!` 处理
            render_api_error!({ error: service_response.message }, service_response.http_status)
          end
        end
      end