본문 바로가기
Spring Framework/스프링

스프링 reCAPTCHA v2 사용하기 [Kotlin]

by 스코리아 2024. 1. 30.

안녕하세요, 스코리아입니다.

오늘은 스프링에서 Google의 reCAPTCHA v2 서비스를 사용하는 방법에 대해서 알아보겠습니다. 언어는 코틀린(Kotlin)으로 진행하겠습니다.

 

구글 reCAPTCHA 소개 (v2, v3)

:: reCAPTCHA v2 ::

- "로봇이 아닙니다" 체크 박스로 잘 알려져 있습니다. 이 체크 박스를 통해 구글 리캡챠는 사용자가 로봇인지 인간인지 판별합니다.

- 이미지 도전 과제가 존재합니다. 사용자가 의심스러운 경우, 교통수단이나 가로등 등을 식별하도록 요구하는 도전과제를 보여주고, 사용자가 풀면 인간임을 확인합니다.

- 다양한 서비스에서 대중적으로 v2가 사용 중입니다.

"로봇이 아닙니다" 체크박스 - v2
"로봇이 아닙니다" 도전과제

 

:: reCAPTCHA v3 ::

- v2보다 진화된 형태로 알려져 있습니다.

- 웹사이트 상호작용 전반에 걸쳐 사용자의 행동을 분석하여 점수를 매깁니다.

- 따로 "로봇이 아닙니다" 체크 박스가 나타나지 않으므로, 직접 테스트하기에는 불편할 수 있습니다.

 

 

현재 reCAPTCHA v2가 대중적으로 사용되고 있고 "로봇이 아닙니다" 체크 박스가 나오므로 테스트하기가 쉽습니다.

그러므로 v2를 사용하도록 하겠습니다.

 

 

reCAPTCHA v2 : 키 발급받기

1. reCAPTCHA 등록하기

https://www.google.com/recaptcha/admin/create 에 접속후, 라벨에 원하는 서비스 이름을 입력해 주세요.

reCAPTCHA 유형은 v2의 "로봇이 아닙니다" 체크박스를 선택하겠습니다.

 

도메인의 경우 프론트 URL을 적어주시면 됩니다. 포트는 따로 적어주실 필요 없습니다.

로컬에서 작업 중이실 경우, 예를 들어 리액트(http://localhost:3000)이라면, localhost만 적어주시면 됩니다.

Step 1

 

2. 사이트 키, 비밀 키를 기억해 두세요.

사이트 키는 프론트에서, 비밀 키는 백엔드에서 사용됩니다.

Step 2

 

 

스프링 프로젝트에 적용하기

1. application.yml 에 사이트키, 비밀키 등록하기

recaptcha:
  secret: 비밀키
  url: https://www.google.com/recaptcha/api/siteverify

 

아까 발급받았던 reCAPTCHA 비밀키를 secret 자리에 넣어주세요.

 

2. reCAPTCHA 서비스 만들기

@Service
class RecaptchaService(
    private val restTemplate: RestTemplate,
    @Value("\${recaptcha.url}") private val verifyUrl: String,
    @Value("\${recaptcha.secret}") private val secretKey: String,
) {
    private fun verifyRecaptcha(response: String): Boolean {
        val params: MultiValueMap<String, String> = LinkedMultiValueMap()
        params.add("secret", secretKey)
        params.add("response", response)

        val headers = HttpHeaders()
        headers.contentType = MediaType.APPLICATION_FORM_URLENCODED

        val request = HttpEntity(params, headers)
        val responseEntity = restTemplate.postForEntity(verifyUrl, request, Map::class.java)
        val responseBody = responseEntity.body as Map<*, *>
        return responseBody["success"] as Boolean
    }

    fun verifyRecaptchaComplete(response: String) {
        require(verifyRecaptcha(response)){
            "구글 캡챠 검증에 실패하였습니다. 다시 시도해주세요."
        }
    }
}

 

우선 언어는 코틀린으로 작성하였습니다.

 

RestTemplateHTTP 요청을 보내기 위한 스프링의 템플릿입니다. @Value 어노테이션을 이용해서 application.yml에 적어둔 secret(비밀키), url(reCAPTCHA 검증 주소)를 가져왔습니다.

 

HTTP 요청에 포함될 파라미터로 secret 키와 reposnse를 넘겨주었고, 이와 함께 APPLICATION_FORM_URLENCODED 헤더를 이용해서 POST 요청을 보냈습니다. (reCAPTCHA API에 응답을 보내기 위해서는 해당 헤더가 필히 필요합니다)

응답받은 Body가 JSON이므로, reponseBody ["success"]를 이용해서 검증이 통과하였는지 실패하였는지 Boolean으로 반환하였습니다.

 

verifyRecaptchaComplete 메소드에서는 reCAPTCHA 검증이 실패하면 사용자에게 throw를 던집니다. (require 함수는 주어진 조건이 "false"일 경우 예외를 던집니다)

 

3. reCAPTCHA를 적용하기

fun signUpVerificationSendEmail(signUpVerificationSendEmailDtoRequest: SignUpVerificationSendEmailDtoRequest): EmailVerificationDtoResponse {
    // reCAPTCHA 적용하기
    recaptchaService.verifyRecaptchaComplete(signUpVerificationSendEmailDtoRequest.recaptchaResponse)

    checkDuplicateEmail(signUpVerificationSendEmailDtoRequest.email) // email 중복 검사

    return verificationSendEmail(
        "SignUp",
        signUpVerificationSendEmailDtoRequest.email,
        "회원가입 인증번호 안내",
        "회원가입을 위해서 아래 인증코드를 입력해주세요."
    )
}

 

위 코드는 MemberService 안에 회원가입 시 이메일을 검증하기 위해 발송하는 서비스 함수입니다. reCAPTCHA를 적용하기 위해 recaptchaService.verifyRecaptchaComplete(response) 1줄을 추가하여 reCAPTCHA 검증을 끝냈습니다.

 

이렇게 하여 reCAPTCHA가 실패하였다면 throw(예외)가 발생할 것이고, 성공하였다면 그대로 통과될 것입니다.

 


 

이상으로 스프링에서 구글의 reCAPTCHA v2 서비스를 사용하는 방법에 대해서 알아보았습니다.

다음 시간에는 이어서 React(FE)에서 reCAPTCHA v2를 적용하는 방법에 대해서 소개해드리겠습니다.

 

읽어주셔서, 감사합니다.