IT/C#

google reCAPTCHA 적용(v2,v3)

하루콩콩 2025. 2. 14. 10:02
반응형

v2(버전 2) : 나는 로봇이 아닙니다 체크박스

참고 : YOUR_SITE_KEY와 YOUR_SECRET_KEY는 Google reCAPTCHA 관리 콘솔에서 발급받은 실제 키로 변경한다.

 

1. 클라이언트 코드 (HTML)

:HTML 페이지에 reCAPTCHA v2 위젯을 추가

<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <title>reCAPTCHA v2 예제</title>
  <!-- reCAPTCHA API 스크립트 추가 -->
  <script src="https://www.google.com/recaptcha/api.js" async defer></script>
</head>
<body>
  <form id="myForm" method="post" action="/Home/Verify">
    <!-- 필요한 다른 폼 필드들 추가 가능 -->
    <!-- reCAPTCHA 위젯 (YOUR_SITE_KEY를 실제 사이트 키로 변경) -->
    <div class="g-recaptcha" data-sitekey="YOUR_SITE_KEY"></div>
    <br/>
    <input type="submit" value="제출">
  </form>
</body>
</html>

 

2.서버 코드(응답 모델 클래스)

using System;
using System.Collections.Generic;
using Newtonsoft.Json;

public class RecaptchaResponse
{
    [JsonProperty("success")]
    public bool Success { get; set; }
    
    [JsonProperty("challenge_ts")]
    public DateTime ChallengeTimeStamp { get; set; }
    
    [JsonProperty("hostname")]
    public string HostName { get; set; }
    
    [JsonProperty("error-codes")]
    public List<string> ErrorCodes { get; set; }
}

 

3.서버코드(컨트롤러 내 검증)

using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace YourNamespace.Controllers
{
    public class HomeController : Controller
    {
        // 발급받은 시크릿 키로 변경하세요.
        private const string RecaptchaSecret = "YOUR_SECRET_KEY";

        [HttpPost]
        public async Task<IActionResult> Verify(string gRecaptchaResponse)
        {
            // 클라이언트 IP (옵션)
            string remoteIp = HttpContext.Connection.RemoteIpAddress?.ToString();

            // POST 데이터 구성
            var values = new Dictionary<string, string>
            {
                { "secret", RecaptchaSecret },
                { "response", gRecaptchaResponse },
                { "remoteip", remoteIp }
            };

            using (var client = new HttpClient())
            {
                var content = new FormUrlEncodedContent(values);
                var apiResponse = await client.PostAsync("https://www.google.com/recaptcha/api/siteverify", content);
                var jsonResponse = await apiResponse.Content.ReadAsStringAsync();

                // JSON 응답을 RecaptchaResponse 모델로 역직렬화
                var recaptchaResult = JsonConvert.DeserializeObject<RecaptchaResponse>(jsonResponse);

                if (recaptchaResult.Success)
                {
                    // 검증 성공: 정상적인 사용자로 간주
                    return Content("reCAPTCHA 검증에 성공했습니다.");
                }
                else
                {
                    // 검증 실패: 봇일 가능성이 있음
                    return Content("reCAPTCHA 검증에 실패했습니다. 다시 시도해주세요.");
                }
            }
        }
    }
}

-----------------------------------------------------------------------------------------------------------------------------------------------------------------v3(버전 3) : 백그라운드에서 작동, 별도 위젯(나는 로봇이 아닙니다 체크박스) 필요없음

1.클라이언트 코드(HTML)

<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <title>reCAPTCHA v3 C# 예제</title>
  <!-- 발급받은 사이트 키(YOUR_SITE_KEY)로 변경 -->
  <script src="https://www.google.com/recaptcha/api.js?render=YOUR_SITE_KEY"></script>
</head>
<body>
  <form id="myForm" method="post" action="/Home/Verify">
    <!-- 필요한 다른 폼 필드들을 추가하세요 -->
    <!-- reCAPTCHA 토큰을 저장할 숨겨진 필드 -->
    <input type="hidden" name="g-recaptcha-response" id="g-recaptcha-response">
    <input type="submit" value="제출">
  </form>

  <script>
    // 페이지 로드 후 reCAPTCHA 토큰 생성
    grecaptcha.ready(function() {
      // action 값은 상황에 맞게 지정 (예: 'submit')
      grecaptcha.execute('YOUR_SITE_KEY', {action: 'submit'}).then(function(token) {
          // 토큰을 숨겨진 필드에 저장
          document.getElementById('g-recaptcha-response').value = token;
      });
    });
  </script>
</body>
</html>

 

2.서버코드(응답 모델 클래스)

using System;
using System.Collections.Generic;
using Newtonsoft.Json;

public class RecaptchaResponse
{
    [JsonProperty("success")]
    public bool Success { get; set; }

    [JsonProperty("score")]
    public float Score { get; set; }

    [JsonProperty("action")]
    public string Action { get; set; }

    [JsonProperty("challenge_ts")]
    public DateTime ChallengeTimeStamp { get; set; }

    [JsonProperty("hostname")]
    public string HostName { get; set; }

    [JsonProperty("error-codes")]
    public List<string> ErrorCodes { get; set; }
}

 

3.서버 코드(컨트롤러 내 검증) 

using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace YourNamespace.Controllers
{
    public class HomeController : Controller
    {
        // 발급받은 시크릿 키(YOUR_SECRET_KEY)로 변경
        private const string RecaptchaSecret = "YOUR_SECRET_KEY";

        [HttpPost]
        public async Task<IActionResult> Verify(string gRecaptchaResponse)
        {
            // 클라이언트로부터 넘어온 토큰(gRecaptchaResponse)과 클라이언트 IP
            string remoteIp = HttpContext.Connection.RemoteIpAddress?.ToString();

            // Google reCAPTCHA 검증 API 호출을 위한 POST 데이터 구성
            var values = new Dictionary<string, string>
            {
                { "secret", RecaptchaSecret },
                { "response", gRecaptchaResponse },
                { "remoteip", remoteIp }
            };

            using (var client = new HttpClient())
            {
                var content = new FormUrlEncodedContent(values);
                var apiResponse = await client.PostAsync("https://www.google.com/recaptcha/api/siteverify", content);
                var jsonResponse = await apiResponse.Content.ReadAsStringAsync();

                // 응답 JSON을 RecaptchaResponse 모델로 역직렬화
                var recaptchaResult = JsonConvert.DeserializeObject<RecaptchaResponse>(jsonResponse);

                /*
                  응답 예시:
                  {
                    "success": true,
                    "score": 0.9,
                    "action": "submit",
                    "challenge_ts": "2025-02-14T12:34:56Z",
                    "hostname": "yourdomain.com"
                  }
                */

                // 임계값(threshold)은 서비스에 맞게 조정 (예: 0.5 이상이면 정상)
                if (recaptchaResult.Success && recaptchaResult.Score >= 0.5 && recaptchaResult.Action == "submit")
                {
                    // 검증 성공: 정상적인 사용자의 요청으로 간주
                    return Content("reCAPTCHA 검증에 성공했습니다.");
                }
                else
                {
                    // 검증 실패: 봇일 가능성이 높음
                    return Content("reCAPTCHA 검증에 실패했습니다. 다시 시도해주세요.");
                }
            }
        }
    }
}

반응형