REST API 스팸 방지 및 CAPTCHA 지원
모델을 REST API를 통해 수정할 수 있다면, 스팸 가능성이 있는 속성을 수정할 수 있는 모든 관련 API 엔드포인트에도 지원을 추가해야 합니다. 이는 POST
및 PUT
뮤테이션을 확실히 포함하지만, 모델의 비밀/공개 플래그를 변경하는 것과 관련된 것과 같이 다른 엔드포인트도 포함될 수 있습니다.
REST 엔드포인트에 지원 추가
주요 단계는 다음과 같습니다:
-
resource
에서helpers SpammableActions::CaptchaCheck::RestApiActionsSupport
를 추가합니다. - Update 서비스 클래스 생성자에
perform_spam_check: true
를 전달합니다. Create 서비스에서는 기본적으로true
로 설정됩니다. -
Spammable
모델 인스턴스를 생성하거나 업데이트한 후,#check_spam_action_response!
를 호출하여 생성된 또는 업데이트된 인스턴스를 변수에 저장합니다. - 요청의 ‘failure’ 케이스에 대한 오류 처리 로직을 식별합니다. 생성 또는 업데이트에 성공하지 못했을 때, 가능한 스팸 감지의 인디케이터로 사용됩니다. 이는
Spammable
인스턴스에 오류를 추가합니다. 이 오류는 일반적으로render_api_error!
또는render_validation_error!
와 유사합니다. - 기존 오류 처리 로직을
with_captcha_check_rest_api(spammable: my_spammable_instance)
호출로 감싸서 기존 에러 처리 로직을 실행합니다. 이 때,Spammable
모델 인스턴스를 변수에 저장한 후spammable:
이름 있는 인자로 전달합니다. 이 호출은 다음을 수행합니다:- 모델에서 필요한 스팸 확인을 수행합니다.
- 스팸이 감지되면:
- 설명적인 스팸 특정 오류 메시지를 가진 Grape
#error!
익셉션을 발생시킵니다. - 응답에 에러 필드로 추가된 관련 정보를 포함합니다. 이러한 필드에 대한 자세한 내용은 REST API 문서의 스팸으로 감지된 요청 해결 섹션을 참조하세요.
- 설명적인 스팸 특정 오류 메시지를 가진 Grape
앞서 설명한 표준 ApolloLink 또는 Axios 인터셉터 CAPTCHA 지원을 사용하는 경우, 자동으로 처리되기 때문에 필드 세부 정보를 무시할 수 있습니다. GraphQL API를 직접 사용하여 잠재적인 스팸을 확인하고 해결된 CAPTCHA 응답으로 요청을 다시 제출하려고 하는 경우에 이 정보가 관련이 있습니다.
snippets
리소스에서 post
및 put
액션에 대한 예는 다음과 같습니다:
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
end
end
end