SafetyNet 서비스에는 악성 트래픽으로부터 앱을 보호하기 위해 사용할 수 있는 reCAPTCHA API가 포함됩니다.
reCAPTCHA는 고급 위험 분석 엔진을 사용해 스팸 및 다른 악용 작업으로부터 앱을 보호하는 무료 서비스입니다. 이 서비스는 앱과 상호작용 중인 사용자가 사람이 아니라 봇일 수 있다고 의심하면 사람이 해결해야만 앱 실행이 계속될 수 있게 하는 보안문자를 제공합니다.
이 문서에서는 SafetyNet의 reCAPTCHA API를 앱에 통합하는 방법을 설명합니다.
추가 서비스 약관
reCAPTCHA API에 액세스하거나 이를 사용하면 Google API 서비스 약관 및 다음 reCAPTCHA 서비스 약관에 동의하는 것으로 간주됩니다. SafetyNet API에 액세스하기 전에 모든 관련 약관 및 정책을 자세히 읽고 숙지하시기 바랍니다.
reCAPTCHA 서비스 약관
기기, 애플리케이션 데이터, 무결성 검사 결과와 같은 하드웨어 및 소프트웨어 정보를 수집하고 분석을 위해 이러한 데이터를 Google에 보내는 reCAPTCHA API의 작업을 인정하고 이해하는 것으로 간주됩니다. Google API 서비스 약관의 3(d)항에 따라, reCAPTCHA API를 사용하면 이러한 데이터를 수집하고 Google과 공유하는 데 필요한 고지 또는 동의를 제공하는 책임이 개발자에게 있다는 것에 동의하는 것으로 간주됩니다.reCAPTCHA 키 쌍 등록하기
SafetyNet reCAPTCHA API에 사용하도록 키 쌍을 등록하려면 reCAPTCHA Android 가입 사이트로 이동한 후 다음 단계를 순서대로 완료하세요.
양식이 표시되면 다음 정보를 제공합니다.
- 라벨: 키의 고유한 라벨입니다. 일반적으로 회사나 조직의 이름을 사용합니다.
- reCAPTCHA 유형: reCAPTCHA v2를 선택한 다음 reCAPTCHA Android를 선택합니다.
- 패키지: 이 API 키를 사용하는 각 앱의 패키지 이름을 제공합니다. 앱에서 API를 사용하려면 입력하는 패키지 이름이 앱의 패키지 이름과 정확히 일치해야 합니다. 각 패키지 이름을 한 줄에 하나씩 입력합니다.
- 소유자: 조직에서 앱의 reCAPTCHA 평가를 모니터링하는 각 개인의 이메일 주소를 추가합니다.
reCAPTCHA 서비스 약관에 동의 체크박스를 선택합니다.
소유자에게 알림 보내기: reCAPTCHA API에 관한 이메일을 받으려면 이 체크박스를 선택한 다음 제출을 클릭합니다.
다음에 표시되는 페이지에서 사이트 키와 보안 비밀 키 아래에 공개 키와 비공개 키가 각각 표시됩니다. 사이트 키는 인증 요청을 보낼 때 사용하고 보안 비밀 키는 사용자 응답 토큰을 검증할 때 사용합니다.
SafetyNet API 종속 항목 추가
reCAPTCHA API를 사용하기 전에 프로젝트에 SafetyNet API를 추가하세요. Android 스튜디오를 사용한다면 이 종속 항목을 앱 수준 Gradle 파일에 추가하세요. 자세한 내용은 SafetyNet API 설정을 참고하세요.
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}") } }) }
Java
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()
메서드를 실행하면 사용자가 보안문자 질문에 성공적으로 답변한 것입니다. 하지만 이 메서드는 사용자가 보안문자를 올바르게 해결했다는 것만 나타냅니다. 여전히 백엔드 서버에서 사용자의 응답 토큰을 검증해야 합니다.
사용자의 응답 토큰을 검증하는 방법을 알아보려면 사용자의 응답 인증하기를 참고하세요.