CAPTCHA의 탐색적 테스트

리뷰 앱 및 로컬 개발 환경(GDK)에서 CAPTCHA를 신뢰할 수 있게 테스트할 수 있습니다. 항상 다음을 할 수 있습니다:

  • 지원되는 경우 reCAPTCHA를 표시하도록 강제합니다.
  • 길거리 표지 이미지를 찾고 선택하는 대신 체크박스를 표시하도록 강제합니다.

테스트를 설정하려면 이 페이지의 구성을 따르세요.

적절한 테스트 데이터 사용

스팸/CAPTCHA가 사용된 시나리오를 테스트하는지 확인하세요. 예를 들어: 스프램을 확인하는 것은 공개 스니펫을 편집하는지 확인하세요. 왜냐하면 공개 스니펫만이 스팸 확인 대상입니다.

피처 플래그 활성화

스팸/CAPTCHA 지원이 피처 플래그 뒤에 숨겨져 있는 경우 관련 피처 플래그를 활성화하세요.

Akismet 및 reCAPTCHA 설정

  1. reCAPTCHA 설정:
    1. GitLab reCAPTCHA 문서를 검토합니다.
    2. Google의 reCAPTCHA 문서의 지침을 사용하여 Google의 공식 테스트 reCAPTCHA 자격 증명을 가져옵니다.
      1. 사이트 키로 사용할 것: 6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI
      2. 비밀 키로 사용할 것: 6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe
    3. Admin -> 설정 -> 보고서 설정으로 이동: http://gdk.test:3000/admin/application_settings/reporting#js-spam-settings
    4. 스팸 및 안티봇 보호 섹션을 확장합니다.
    5. reCAPTCHA 사용을 선택하세요. 로그인을 위해 활성화할 경우를 제외하고요.
    6. 사이트 키비밀 키를 입력하세요.
  2. Akismet 설정:
    1. Akismet에 대한 GitLab 문서를 검토합니다.
    2. Akismet API 키를 가져옵니다. Akismet에서 테스트 키를 가입하여 가입할 때 로컬 호스트(예: gdk.test) 및 이메일을 입력해야 합니다.
    3. GitLab Akismet 설정 페이지로 이동하세요, 예를 들어: http://gdk.test:3000/admin/application_settings/reporting#js-spam-settings
    4. Akismet을 활성화하고 Akismet API 키를 입력하세요.
  3. Akismet 거짓 양성 스팸 확인을 강제하려면, Akismet API 문서Akismet 시작하기 문서를 참조하여 자세한 정보를 확인하세요:
    1. 다음 단계를 사용하여 akismet-guaranteed-spam@example.com을 이용해 스팸을 강제할 수 있습니다:
      1. 사용자 이메일 설정으로 이동하세요: http://gdk.test:3000/-/profile/emails
      2. akismet-guaranteed-spam@example.com을 관리자 사용자의 보조 이메일로 추가하세요.
      3. 레일즈 콘솔에서 확인하세요: bin/rails c -> User.find_by_username('root').emails.last.confirm
      4. 이 확인된 이메일을 기본 이메일로 변경하세요:
        1. 아바타 드롭다운 목록 -> 프로필 편집 -> 기본 설정으로 이동하세요.
        2. 이메일admin@example.com을 대체하는 akismet-guaranteed-spam@example.com을 입력하세요.
        3. 변경 사항을 저장하려면 프로필 설정 업데이트을 선택하세요.

웹 UI에서 테스트

위의 구성을 모두 갖추면 CAPTCHA를 테스트할 수 있습니다. CAPTCHA 지원이 이미 있는 애플리케이션 영역에서 테스트하세요. 예를 들어:

  • 이슈를 생성하거나 편집합니다.
  • 공개 스니펫을 만들거나 편집합니다. 스팸 확인은 공개 스니펫에 대해서만 수행됩니다.

개발 환경에서 테스트

위의 단계를 사용하여 스팸 플래깅 + CAPTCHA를 강제한 후에, 스팸 보호된 모델/컨트롤러 액션을 테스트할 수 있습니다.

CAPTCHA 사용으로 테스트(조건부 허용 판정)

다음 영역에서 CAPTCHA가 활성화된 경우에는 양식을 다시 제출하기 전에 CAPTCHA 팝업 모달을 해결해야 합니다:

  • Admin -> 설정 -> 보고서 -> 스팸
  • 안티봇 보호 -> reCAPTCHA 활성화

CAPTCHA 비활성화로 테스트(“허용 안 함” 판정)

Admin -> 설정 -> 보고서 -> 스팸안티봇 보호 -> reCAPTCHA 활성화에서 CAPTCHA가 비활성화된 경우에는 CAPTCHA 팝업이 표시되지 않습니다. 양식을 아예 제출할 수 없습니다.

reCAPTCHA를 렌더링하는 HTML 페이지

참고: Set up Akismet and reCAPTCHA에 있는 Google의 공식 테스트 reCAPTCHA 자격 증명을 사용하는 경우 CAPTCHA 응답 문자열은 중요하지 않습니다. 아무 문자열이어도 상관없습니다. 실제 유효한 키 쌍을 사용하는 경우에도 유효한 CAPTCHA 응답을 얻기 위해 CAPTCHA를 해결해야 합니다. 이것은 딱 한 번만 하면 되며, 유효 기간이 만료되기 전에만 가능합니다.

GraphQL Explorer를 통해 직접 GraphQL API를 테스트하려면 (http://gdk.test:3000/-/graphql-explorer), 이 형식을 사용하여 reCAPTCHA 응답 문자열을 가져올 수 있습니다: public/recaptcha.html (http://gdk.test:3000/recaptcha.html):

<html>
<head>
  <title>reCAPTCHA demo: Explicit render after an onload callback</title>
  <script type="text/javascript">
  var onloadCallback = function() {
    grecaptcha.render('html_element', {
      'sitekey' : '6Ld05AsaAAAAAMsm1yTUp4qsdFARN15rQJPPqv6i'
    });
  };
  function onSubmit() {
    window.document.getElementById('recaptchaResponse').innerHTML = grecaptcha.getResponse();
    return false;
  }
  </script>
</head>
<body>
<form onsubmit="return onSubmit()">
  <div id="html_element"></div>
  <br>
  <input type="submit" value="Submit">
</form>
<div>
  <h1>recaptchaResponse:</h1>
  <div id="recaptchaResponse"></div>
</div>
<script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit"
        async defer>
</script>
</body>
</html>

스팸/CAPTCHA API 탐색적 테스트 예제

이러한 섹션은 REST 및 GraphQL API의 스팸 및 CAPTCHA 동작의 여러 시나리오를 수동으로 탐색적으로 테스트하기 위해 필요한 단계를 설명합니다.

전제 조건으로 다음을 수행해야 합니다.

  1. 개발 환경에서 스팸 및 CAPTCHA를 활성화하고, 양식 제출을 강제로 CAPTCHA가 필요하게 하기 위해 위에 나열된 모든 단계 수행.
  2. /public 디렉토리 아래에 CAPTCHA를 렌더링하는 HTML 페이지를 생성했는지 확인, 유효한 CAPTCHA 응답 문자열을 수동으로 생성하는 양식을 포함하는 페이지를 만들었는지 확인. Akismet 및 reCAPTCHA 설정에 나열된 Google의 공식 테스트 reCAPTCHA 자격 증명을 사용하는 경우, CAPTCHA 응답 문자열의 내용은 중요하지 않습니다.
  3. Admin -> Settings -> Reporting -> Spam and Anti-bot Protection으로 이동합니다.
  4. 시나리오의 요구 사항에 따라 reCAPTCHA 활성화Akismet 활성화를 선택하거나 해제합니다.

다음 예제는 스니펫 생성을 예로 들고 있습니다. 스니펫 업데이트, 이슈 생성 또는 이슈 업데이트를 사용할 수도 있습니다. 이슈와 스니펫은 완전한 스팸 및 CAPTCHA 지원을 제공하는 유일한 모델입니다.

초기 설정

  1. API 토큰을 생성합니다.
  2. REST 명령어를 위해 터미널에서 이를 내보냅니다: export PRIVATE_TOKEN=<your_api_token>
  3. GraphQL 쿼리를 실행하기 전에 localhost:3000의 GitLab 개발 환경에 로그인했는지 확인하세요. GraphiQL 탐색기는 인증된 사용자를 사용하여 GraphQL 쿼리를 실행하는 권한으로 사용합니다.
  4. GraphQL 예제에서는 http://localhost:3000/-/graphql-explorer의 GraphiQL 탐색기를 사용합니다.
  5. curl--include (-i) 옵션을 사용하여 상태 코드를 포함한 HTTP 응답 헤더를 출력합니다.

시나리오: Akismet 및 CAPTCHA 활성화

이 예제에서는 Akismet 및 CAPTCHA가 활성화되어 있습니다.

  1. 초기 요청.

초기 요청

이 초기 요청은 CAPTCHA 응답이 제공되지 않아 실패합니다.

REST 요청:

curl --request POST --header "PRIVATE-TOKEN: $PRIVATE_TOKEN" "http://localhost:3000/api/v4/snippets?title=Title&file_name=FileName&content=Content&visibility=public"

REST 응답:

{"needs_captcha_response":true,"spam_log_id":42,"captcha_site_key":"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX","message":{"error":"Your snippet has been recognized as spam. Please, change the content or solve the reCAPTCHA to proceed."}}

GraphQL 요청:

mutation {
    createSnippet(input: {
        title: "Title"
        visibilityLevel: public
        blobActions: [
            {
                action: create
                filePath: "BlobPath"
                content: "BlobContent"
            }
        ]
    }) {
        snippet {
            id
            title
        }
        errors
    }
}

GraphQL 응답:

{
  "data": {
    "createSnippet": null
  },
  "errors": [
    {
      "message": "Request denied. Solve CAPTCHA challenge and retry",
      "locations": [
        {
          "line": 22,
          "column": 5
        }
      ],
      "path": [
        "createSnippet"
      ],
      "extensions": {
        "needs_captcha_response": true,
        "spam_log_id": 140,
        "captcha_site_key": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
      }
    }
  ]
}

두 번째 요청

이 요청은 CAPTCHA 응답이 제공되어 성공합니다.

REST 요청:

export CAPTCHA_RESPONSE="<CAPTCHA response obtained from HTML page to render CAPTCHA>"
export SPAM_LOG_ID="<spam_log_id obtained from initial REST response>"
curl --request POST --header "PRIVATE-TOKEN: $PRIVATE_TOKEN" --header "X-GitLab-Captcha-Response: $CAPTCHA_RESPONSE" --header "X-GitLab-Spam-Log-Id: $SPAM_LOG_ID" "http://localhost:3000/api/v4/snippets?title=Title&file_name=FileName&content=Content&visibility=public"

REST 응답:

{"id":42,"title":"Title","description":null,"visibility":"public", "other_fields": "..."}

GraphQL 요청:

참고: GitLab의 GraphiQL 구현은 헤더를 전달하는 것을 허용하지 않으므로, 여기서는 curl 쿼리로 작성해야 합니다. 여기서 JSON에 포함된 쿼리의 이스케이프된 이중 인용부호를 제대로 처리하기 위해 --data-binary를 사용합니다.

export CAPTCHA_RESPONSE="<CAPTCHA response obtained from HTML page to render CAPTCHA>"
export SPAM_LOG_ID="<spam_log_id obtained from initial REST response>"
curl --include "http://localhost:3000/api/graphql" --header "Authorization: Bearer $PRIVATE_TOKEN" --header "Content-Type: application/json" --header "X-GitLab-Captcha-Response: $CAPTCHA_RESPONSE" --header "X-GitLab-Spam-Log-Id: $SPAM_LOG_ID" --request POST --data-binary '{"query": "mutation {createSnippet(input: {title: \"Title\" visibilityLevel: public blobActions: [ { action: create filePath: \"BlobPath\" content: \"BlobContent\" } ] }) { snippet { id title } errors }}"}'

GraphQL 응답:

{"data":{"createSnippet":{"snippet":{"id":"gid://gitlab/PersonalSnippet/42","title":"Title"},"errors":[]}}}

시나리오: Akismet 활성화, CAPTCHA 비활성화

이 시나리오에서는 Admin 영역 설정에서 reCAPTCHA 활성화를 해제했는지 확인하세요. CAPTCHA가 비활성화된 경우, CAPTCHA가 활성화되고 성공적으로 해결된다면 다시 제출할 수 있는 경우라도 잠재적 스팸으로 표시된 모든 요청은 실패합니다.

REST 요청은 CAPTCHA가 활성화된 경우와 동일합니다:

curl --request POST --header "PRIVATE-TOKEN: $PRIVATE_TOKEN" "http://localhost:3000/api/v4/snippets?title=Title&file_name=FileName&content=Content&visibility=public"

REST 응답:

{"message":{"error":"Your snippet has been recognized as spam and has been discarded."}}

GraphQL 요청:

mutation {
    createSnippet(input: {
        title: "Title"
        visibilityLevel: public
        blobActions: [
            {
                action: create
                filePath: "BlobPath"
                content: "BlobContent"
            }
        ]
    }) {
        snippet {
            id
            title
        }
        errors
    }
}

GraphQL 응답:

{
  "data": {
    "createSnippet": null
  },
  "errors": [
    {
      "message": "Request denied. Spam detected",
      "locations": [
        {
          "line": 22,
          "column": 5
        }
      ],
      "path": [
        "createSnippet"
      ],
      "extensions": {
        "spam": true
      }
    }
  ]
}

시나리오: allow_possible_spam 애플리케이션 설정 활성화

allow_possible_spam 애플리케이션 설정을 활성화하면 API는 200 응답을 반환합니다. 모든 유효한 요청은 성공하며, 요청이 스팸으로 간주되더라도 CAPTCHA가 표시되지 않습니다.