SafetyNet reCAPTCHA API

SafetyNet 서비스에는 악성 트래픽으로부터 앱을 보호하기 위해 사용할 수 있는 reCAPTCHA API가 포함됩니다.

reCAPTCHA는 고급 위험 분석 엔진을 사용해 스팸 및 다른 악용 작업으로부터 앱을 보호하는 무료 서비스입니다. 이 서비스는 앱과 상호작용 중인 사용자가 사람이 아니라 봇일 수 있다고 의심하면 사람이 해결해야만 앱 실행이 계속될 수 있게 하는 보안문자를 제공합니다.

이 문서에서는 SafetyNet의 reCAPTCHA API를 앱에 통합하는 방법을 설명합니다.

추가 서비스 약관

reCAPTCHA API에 액세스하거나 reCAPTCHA API를 사용하면 Google API 서비스 약관 및 이 추가 약관에 동의하게 됩니다. reCAPTCHA API에 액세스하기 전에 모든 관련 약관 및 정책을 자세히 읽고 숙지하시기 바랍니다.

reCAPTCHA 서비스 약관

기기, 애플리케이션 데이터, 무결성 검사 결과와 같은 하드웨어 및 소프트웨어 정보를 수집하고 분석을 위해 이러한 데이터를 Google에 보내는 reCAPTCHA API의 작업을 인정하고 이해하는 것으로 간주됩니다. Google API 서비스 약관의 3(d)항에 따라, reCAPTCHA API를 사용하면 이러한 데이터를 수집하고 Google과 공유하는 데 필요한 고지 또는 동의를 제공하는 책임이 개발자에게 있다는 것에 동의하는 것으로 간주됩니다.

reCAPTCHA 키 쌍 등록하기

SafetyNet reCAPTCHA API에 사용할 키 쌍을 등록하려면 reCAPTCHA Android 가입 사이트로 이동한 후 다음 단계를 순서대로 완료하세요.

  1. 양식이 표시되면 다음 정보를 제공합니다.

    • 라벨: 키의 고유한 라벨입니다. 일반적으로 회사나 조직의 이름을 사용합니다.
    • 패키지 이름: 이 API 키를 사용하는 각 앱의 패키지 이름을 제공합니다. 앱이 API를 사용하려면 입력하는 패키지 이름이 앱의 패키지 이름과 정확히 일치해야 합니다. 각 패키지 이름을 한 줄에 하나씩 입력합니다.
    • 소유자에게 알림 보내기: reCAPTCHA API에 관한 이메일을 받으려면 이 체크박스를 선택합니다.
  2. reCAPTCHA 서비스 약관에 동의 체크박스를 선택한 후 등록을 클릭합니다.

  3. 다음에 표시되는 페이지의 앱에 reCAPTCHA 추가 섹션에서 사이트 키 아래에 공개 키가, 보안 비밀 키 아래에 비공개 키가 표시됩니다. 사이트 키는 인증 요청을 보낼 때 사용하고 보안 비밀 키는 사용자 응답 토큰을 검증할 때 사용합니다.

SafetyNet API 종속성 추가하기

reCAPTCHA API를 사용하기 전에 프로젝트에 SafetyNet API를 추가해야 합니다. Android 스튜디오를 사용하며 이 API를 Gradle 종속 항목으로 선택적으로 컴파일하려면 다음 코드 스니펫에 나와 있는 빌드 규칙을 포함해야 합니다.

    apply plugin: 'com.android.application'
    ...
    dependencies {
        compile 'com.google.android.gms:play-services-safetynet:17.0.0'
    }
    

자세한 내용은 Google Play 서비스 설정을 참조하세요.

reCAPTCHA API 사용하기

이 섹션에서는 reCAPTCHA API를 호출하여 보안문자 인증 요청을 보내고 사용자 응답 토큰을 받는 방법을 설명합니다.

인증 요청 보내기

SafetyNet reCAPTCHA API를 호출하려면 verifyWithRecaptcha() 메서드를 호출합니다. 일반적으로 이 메서드는 앱 활동에서 사용자가 버튼과 같은 UI 요소를 선택하는 것에 해당합니다.

앱에서 verifyWithRecaptcha() 메서드 사용 시 다음을 실행해야 합니다.

  • API 사이트 키를 매개변수로 전달합니다.
  • 인증 요청 작업에서 가능한 두 결과를 모두 처리하도록 onSuccess()onFailure() 메서드를 재정의합니다. 특히 API가 ApiException 인스턴스를 onFailure()로 전달하면 getStatusCode()를 사용하여 가져올 수 있는 각각의 가능한 상태 코드를 처리해야 합니다. 자세한 내용은 통신 오류 처리하기를 참조하세요.

다음 코드 스니펫은 이 메서드를 호출하는 방법을 보여줍니다.

Kotlin

    fun onClick(view: View) {
        SafetyNet.getClient(this).verifyWithRecaptcha(YOUR_API_SITE_KEY)
                .addOnSuccessListener(this as Executor, OnSuccessListener { response ->
                    // Indicates communication with reCAPTCHA service was
                    // successful.
                    val userResponseToken = response.tokenResult
                    if (response.tokenResult?.isNotEmpty() == true) {
                        // Validate the user response token using the
                        // reCAPTCHA siteverify API.
                    }
                })
                .addOnFailureListener(this as Executor, OnFailureListener { e ->
                    if (e is ApiException) {
                        // An error occurred when communicating with the
                        // reCAPTCHA service. Refer to the status code to
                        // handle the error appropriately.
                        Log.d(TAG, "Error: ${CommonStatusCodes.getStatusCodeString(e.statusCode)}")
                    } else {
                        // A different, unknown type of error occurred.
                        Log.d(TAG, "Error: ${e.message}")
                    }
                })
    }
    

자바

    public void onClick(View v) {
        SafetyNet.getClient(this).verifyWithRecaptcha(YOUR_API_SITE_KEY)
            .addOnSuccessListener((Executor) this,
                new OnSuccessListener<SafetyNetApi.RecaptchaTokenResponse>() {
                    @Override
                    public void onSuccess(SafetyNetApi.RecaptchaTokenResponse response) {
                        // Indicates communication with reCAPTCHA service was
                        // successful.
                        String userResponseToken = response.getTokenResult();
                        if (!userResponseToken.isEmpty()) {
                            // Validate the user response token using the
                            // reCAPTCHA siteverify API.
                        }
                    }
            })
            .addOnFailureListener((Executor) this, new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        if (e instanceof ApiException) {
                            // An error occurred when communicating with the
                            // reCAPTCHA service. Refer to the status code to
                            // handle the error appropriately.
                            ApiException apiException = (ApiException) e;
                            int statusCode = apiException.getStatusCode();
                            Log.d(TAG, "Error: " + CommonStatusCodes
                                    .getStatusCodeString(statusCode));
                        } else {
                            // A different, unknown type of error occurred.
                            Log.d(TAG, "Error: " + e.getMessage());
                        }
                    }
            });
    }
    

사용자 응답 토큰 검증하기

reCAPTCHA API가 onSuccess() 메서드를 실행하면 사용자가 보안문자 질문에 성공적으로 답변한 것입니다. 하지만 이 메서드는 사용자가 보안문자를 올바르게 해결했다는 것만 나타냅니다. 여전히 백엔드 서버에서 사용자의 응답 토큰을 검증해야 합니다.

사용자의 응답 토큰을 검증하는 방법을 알아보려면 사용자의 응답 인증하기를 참조하세요.

통신 오류 처리하기

앱이 reCAPTCHA 서비스와 통신할 수 없다면 API에서 오류가 발생했기 때문일 수 있습니다. 이러한 오류를 정상적으로 처리하는 로직을 앱에 추가해야 합니다. 또한 오류가 발생하면 앱이 보안문자 응답 처리를 완료할 수 없는 이유를 설명하는 메시지를 사용자에게 표시해야 합니다.

다음 목록은 가장 일반적인 API 오류의 상태 코드를 보여줍니다.

RECAPTCHA_INVALID_SITEKEY

사이트 키가 잘못되었습니다. API를 호출할 때 API 키를 등록했는지 그리고 사이트 키를 올바르게 매개변수로 복사했는지 확인하세요.

상수 값: 12007

RECAPTCHA_INVALID_KEYTYPE

사이트 키의 유형이 잘못되었습니다. reCAPTCHA Android 가입 사이트로 이동하여 새 사이트 키를 만드세요.

상수 값: 12008

RECAPTCHA_INVALID_PACKAGE_NAME

호출 앱의 패키지 이름이 사이트 키와 연결한 이름과 일치하지 않습니다. reCAPTCHA 관리 콘솔에서 호출 앱의 패키지 이름을 사이트 키에 추가하거나 사이트 키의 패키지 이름 검증을 사용 중지하세요.

상수 값: 12013

UNSUPPORTED_SDK_VERSION

API가 기기의 Android SDK 버전에서 지원되지 않습니다. 새 Android SDK 버전으로 업그레이드한 다음 다시 API와 통신해 보세요.

상수 값: 12006

TIMEOUT

API가 응답을 대기할 때 세션이 타임아웃되었습니다. 사용자가 보안문자와 상호작용하지 않았기 때문이거나 보안문자 로드 프로세스 자체가 타임아웃되었기 때문입니다. 사용자가 다시 API를 호출하도록 대기하세요. 기다리는 동안 사용자에게 보안문자를 완료해야 계속 앱을 사용할 수 있다는 것을 알릴 수 있습니다.

상수 값: 15

NETWORK_ERROR

인터넷에 연결되지 않았습니다. 연결을 확인한 후 다시 API와 통신하세요.

상수 값: 7

ERROR

작업에서 일반적인 실패가 발생했습니다.

상수 값: 13

reCAPTCHA API가 반환할 수 있는 상태 코드에 관한 자세한 내용은 SafetyNetStatusCodes 참조를 확인하세요.