Подтвердить что ты не робот

Проверка Recaptcha 2 (не CAPTCHA reCAPTCHA) на стороне сервера ASP.NET

Новый Recaptcha 2 выглядит многообещающим, но я не нашел способ проверить его на стороне сервера ASP.NET,

if(Page.IsValid) в Этот ответ, действителен для старого Recaptcha, но не нового,

Как проверить новую reCAPTCHA на стороне сервера?

4b9b3361

Ответ 1

Прочитав много ресурсов, я написал этот класс для проверки правильности новой ReCaptcha:

Как упомянуто здесь: Когда reCAPTCHA решается конечным пользователем, новое поле (g-recaptcha-response) будет заполнено в HTML.

Нам нужно прочитать это значение и передать его в класс ниже, чтобы проверить его:

В С#:

В коде позади вашей страницы:

string EncodedResponse = Request.Form["g-Recaptcha-Response"];
bool IsCaptchaValid = (ReCaptchaClass.Validate(EncodedResponse) == "true" ? true : false);

if (IsCaptchaValid) {
    //Valid Request
}

Класс:

  using Newtonsoft.Json;

    public class ReCaptchaClass
    {
        public static string Validate(string EncodedResponse)
        {
            var client = new System.Net.WebClient();

            string PrivateKey = "6LcH-v8SerfgAPlLLffghrITSL9xM7XLrz8aeory";

            var GoogleReply = client.DownloadString(string.Format("https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}", PrivateKey, EncodedResponse));

            var captchaResponse = Newtonsoft.Json.JsonConvert.DeserializeObject<ReCaptchaClass>(GoogleReply);

            return captchaResponse.Success.ToLower();
        }

        [JsonProperty("success")]
        public string Success
        {
            get { return m_Success; }
            set { m_Success = value; }
        }

        private string m_Success;
        [JsonProperty("error-codes")]
        public List<string> ErrorCodes
        {
            get { return m_ErrorCodes; }
            set { m_ErrorCodes = value; }
        }


        private List<string> m_ErrorCodes;
    }

В VB.NET:

В коде позади вашей страницы:

Dim EncodedResponse As String = Request.Form("g-Recaptcha-Response")
    Dim IsCaptchaValid As Boolean = IIf(ReCaptchaClass.Validate(EncodedResponse) = "True", True, False)

    If IsCaptchaValid Then
        'Valid Request
    End If

Класс:

Imports Newtonsoft.Json


Public Class ReCaptchaClass
    Public Shared Function Validate(ByVal EncodedResponse As String) As String
        Dim client = New System.Net.WebClient()

        Dim PrivateKey As String = "6dsfH-v8SerfgAPlLLffghrITSL9xM7XLrz8aeory"

        Dim GoogleReply = client.DownloadString(String.Format("https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}", PrivateKey, EncodedResponse))

        Dim captchaResponse = Newtonsoft.Json.JsonConvert.DeserializeObject(Of ReCaptchaClass)(GoogleReply)

        Return captchaResponse.Success
    End Function

    <JsonProperty("success")> _
    Public Property Success() As String
        Get
            Return m_Success
        End Get
        Set(value As String)
            m_Success = value
        End Set
    End Property
    Private m_Success As String

    <JsonProperty("error-codes")> _
    Public Property ErrorCodes() As List(Of String)
        Get
            Return m_ErrorCodes
        End Get
        Set(value As List(Of String))
            m_ErrorCodes = value
        End Set
    End Property

    Private m_ErrorCodes As List(Of String)

End Class

Ответ 2

Здесь используется версия JavaScriptSerializer. Спасибо Ala за основу для этого кода.

Настройка приложения WebConfig - Я добавил секретный ключ к Web.Config в моем случае, чтобы разрешить преобразования между средами. При необходимости он также может быть легко зашифрован.

<add key="Google.ReCaptcha.Secret" value="123456789012345678901234567890" />

Класс ReCaptcha. Простой класс для отправки параметра ответа вместе с вашим секретом в Google и проверки его. Ответ десериализуется с использованием класса .NET JavaScriptSerializer и из возвращаемого значения true или false.

using System.Collections.Generic;
using System.Configuration;

public class ReCaptcha
{   
    public bool Success { get; set; }
    public List<string> ErrorCodes { get; set; }

    public static bool Validate(string encodedResponse)
    {
        if (string.IsNullOrEmpty(encodedResponse)) return false;

        var client = new System.Net.WebClient();
        var secret = ConfigurationManager.AppSettings["Google.ReCaptcha.Secret"];

        if (string.IsNullOrEmpty(secret)) return false;

        var googleReply = client.DownloadString(string.Format("https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}", secret, encodedResponse));

        var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();

        var reCaptcha = serializer.Deserialize<ReCaptcha>(googleReply);

        return reCaptcha.Success;
    }
}

Подтвердить ответ. Проверьте правильность параметра формы g-Recaptcha-Response в вашем контроллере (или код для веб-формы) и выполните соответствующие действия.

var encodedResponse = Request.Form["g-Recaptcha-Response"];
var isCaptchaValid = ReCaptcha.Validate(encodedResponse);

if (!isCaptchaValid)
{
    // E.g. Return to view or set an error message to visible
}   

Ответ 3

Большинство из этих ответов кажутся более сложными, чем необходимо. Они также не указывают IP-адрес, который поможет предотвратить атаку с перехватом (https://security.stackexchange.com/questions/81865/is-there-any-reason-to-include-the-remote-ip-when-using- перепросмотр). Вот на чем я остановился

public bool CheckCaptcha(string captchaResponse, string ipAddress)
{
    using (var client = new WebClient())
    {
        var response = client.DownloadString($"https://www.google.com/recaptcha/api/siteverify?secret={ ConfigurationManager.AppSettings["Google.ReCaptcha.Secret"] }&response={ captchaResponse }&remoteIp={ ipAddress }");
        return (bool)JObject.Parse(response)["success"];
    }
}

Ответ 4

Вы можете использовать метод "IsValidCaptcha()" для проверки Google Recaptcha на стороне сервера. Замените ваш секретный ключ на "YourRecaptchaSecretkey" следующим способом.

Public bool IsValidCaptcha()
 {
  string resp = Request["g-recaptcha-response"];
  var req = (HttpWebRequest)WebRequest.Create
            (https://www.google.com/recaptcha/api/siteverify?secret=+ YourRecaptchaSecretkey + "&response=" + resp);
     using (WebResponse wResponse = req.GetResponse()) 
       {
       using (StreamReader readStream = new StreamReader(wResponse.GetResponseStream()))
         {
          string jsonResponse = readStream.ReadToEnd();
          JavaScriptSerializer js = new JavaScriptSerializer();
          // Deserialize Json
          CaptchaResult data = js.Deserialize<CaptchaResult>(jsonResponse); 
            if (Convert.ToBoolean(data.success))
              {
               return true;
              }
         }
      }
     return false;
 }

Также создайте следующий класс.

public class CaptchaResult
  {
   public string success { get; set; }
  }

Ссылка ссылка

Ответ 5

В соответствии с doc вы просто публикуете свой секретный ключ и пользовательский ответ на API и читаете возвращаемое свойство "success"

КРАТКИЙ ОТВЕТ:

        var webClient = new WebClient();
        string verification = webClient.DownloadString(string.Format("https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}", secretKey, userResponse));
        if (JObject.Parse(verification)["success"].Value<bool>())
        {
            // SUCCESS!!!

ПОЛНЫЙ ПРИМЕР:

Предположим, вы внесете эту страницу в IamNotARobotLogin.cshtml.

<head>
 <script src="https://www.google.com/recaptcha/api.js" async defer></script>
</head>
<body>
<form action="Login" method="POST">
  <div class="g-recaptcha" data-sitekey="your_site_key"></div><br/>
  <input type="submit" value="Log In">
</form>
</body>

И предположим, что вы хотите, чтобы контроллер сохранил, допустим, флаг "I_AM_NOT_ROBOT" в сеансе, если проверка прошла успешно:

    public ActionResult IamNotARobotLogin()
    {
        return View();
    }

    [HttpPost]
    public ActionResult Login()
    {
        const string secretKey = "6LcH-v8SerfgAPlLLffghrITSL9xM7XLrz8aeory";
        string userResponse = Request.Form["g-Recaptcha-Response"];

        var webClient = new System.Net.WebClient();
        string verification = webClient.DownloadString(string.Format("https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}", secretKey, userResponse));

        var verificationJson = Newtonsoft.Json.Linq.JObject.Parse(verification);
        if (verificationJson["success"].Value<bool>())
        {
            Session["I_AM_NOT_A_ROBOT"] = "true";
            return RedirectToAction("Index", "Demo");
        }

        // try again:
        return RedirectToAction("IamNotARobotLogin");
    }

Ответ 6

Здесь моя вилка решения Ala для:

  • отправить параметр в POST
  • для дезинфекции ввода формы
  • включить IP-адрес реквестера
  • хранить секрет в Web.Config:

В контроллере:

bool isCaptchaValid = await ReCaptchaClass.Validate(this.Request);
if (!isCaptchaValid)
{       
    ModelState.AddModelError("", "Invalid captcha");
    return View(model);
}

Класс утилиты:

public class ReCaptchaClass
{
    private static ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
    private static string SecretKey = System.Configuration.ConfigurationManager.AppSettings["Google.ReCaptcha.Secret"];
    [JsonProperty("success")]
    public bool Success { get; set; }
    [JsonProperty("error-codes")]
    public List<string> ErrorCodes { get; set; }

    public static async Task<bool> Validate(HttpRequestBase Request)
    {
        string encodedResponse = Request.Form["g-Recaptcha-Response"];          
        string remoteIp = Request.UserHostAddress;          
        using (var client = new HttpClient())
        {
            var values = new Dictionary<string, string>
            {
               {"secret", SecretKey},
               {"remoteIp", remoteIp},
               {"response", encodedResponse}
            };
            var content = new FormUrlEncodedContent(values);
            var response = await client.PostAsync("https://www.google.com/recaptcha/api/siteverify", content);
            var responseString = await response.Content.ReadAsStringAsync();
            var captchaResponse = Newtonsoft.Json.JsonConvert.DeserializeObject<ReCaptchaClass>(responseString);
            if ((captchaResponse.ErrorCodes?.Count ?? 0) != 0)
            {
                log.Warn("ReCaptcha errors: " + string.Join("\n", captchaResponse.ErrorCodes));
            }
            return captchaResponse.Success;
        }
    }       
}

Ответ 7

Другой пример опубликован здесь:

RecaptchaV2.NET(Github)

Он также реализует опцию безопасного маркера Recaptcha 2.0 (посмотрите на полный исходный код для этого бита, я удалил соответствующие фрагменты кода ТОЛЬКО для проверки результата).

Это не зависит от парсера newtonsoft json и вместо этого использует встроенный .NET.

Вот соответствующий фрагмент кода из библиотеки RecaptchaV2.NET(из recaptcha.cs):

namespace RecaptchaV2.NET
{
  /// <summary>
  /// Helper Methods for the Google Recaptcha V2 Library
  /// </summary>
  public class Recaptcha
  {

    public string SiteKey { get; set; }
    public string SecretKey { get; set; }
    public Guid SessionId { get; set; }

    /// <summary>
    /// Validates a Recaptcha V2 response.
    /// </summary>
    /// <param name="recaptchaResponse">g-recaptcha-response form response variable (HttpContext.Current.Request.Form["g-recaptcha-response"])</param>
    /// <returns>RecaptchaValidationResult</returns>
    public RecaptchaValidationResult Validate(string recaptchaResponse)
    {
      RecaptchaValidationResult result = new RecaptchaValidationResult();

      HttpWebRequest req = (HttpWebRequest)WebRequest.Create("https://www.google.com/recaptcha/api/siteverify?secret=" + SecretKey + "&response="
        + recaptchaResponse + "&remoteip=" + GetClientIp());
      //Google recaptcha Response
      using (WebResponse wResponse = req.GetResponse())
      {
        using (StreamReader readStream = new StreamReader(wResponse.GetResponseStream()))
        {
          string jsonResponse = readStream.ReadToEnd();

          JavaScriptSerializer js = new JavaScriptSerializer();
          result = js.Deserialize<RecaptchaValidationResult>(jsonResponse.Replace("error-codes", "ErrorMessages").Replace("success", "Succeeded"));// Deserialize Json
        }
      }

      return result;
    }

    private string GetClientIp()
    {
      // Look for a proxy address first
      String _ip = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];

      // If there is no proxy, get the standard remote address
      if (string.IsNullOrWhiteSpace(_ip) || _ip.ToLower() == "unknown")
        _ip = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];

      return _ip;
    }
  }

  public class RecaptchaValidationResult
  {
    public RecaptchaValidationResult()
    {
      ErrorMessages = new List<string>();
      Succeeded = false;
    }

    public List<string> ErrorMessages { get; set; }
    public bool Succeeded { get; set; }

    public string GetErrorMessagesString()
    {
      return string.Join("<br/>", ErrorMessages.ToArray());
    }
  }
}

Ответ 8

API Google ReCaptcha больше не принимает полезную нагрузку в качестве параметров строки запроса в запросе GET. Google всегда возвращал "ложный" ответ успеха, если я не отправил данные через HTTP POST. Вот обновление класса Ala (отлично!), Который отправляет полезную нагрузку в конечную точку службы Google:

using Newtonsoft.Json;
using System.Net;
using System.IO;
using System.Text;

public class RecaptchaHandler
{
    public static string Validate(string EncodedResponse, string RemoteIP)
    {
        var client = new WebClient();

        string PrivateKey = "PRIVATE KEY";

        WebRequest req = WebRequest.Create("https://www.google.com/recaptcha/api/siteverify");
        string postData = String.Format("secret={0}&response={1}&remoteip={2}",
                                         PrivateKey,
                                         EncodedResponse,
                                         RemoteIP);

        byte[] send = Encoding.Default.GetBytes(postData);
        req.Method = "POST";
        req.ContentType = "application/x-www-form-urlencoded";
        req.ContentLength = send.Length;

        Stream sout = req.GetRequestStream();
        sout.Write(send, 0, send.Length);
        sout.Flush();
        sout.Close();

        WebResponse res = req.GetResponse();
        StreamReader sr = new StreamReader(res.GetResponseStream());
        string returnvalue = sr.ReadToEnd();

        var captchaResponse = JsonConvert.DeserializeObject<RecaptchaHandler>(returnvalue);

        return captchaResponse.Success;
    }

    [JsonProperty("success")]
    public string Success
    {
        get { return m_Success; }
        set { m_Success = value; }
    }

    private string m_Success;
    [JsonProperty("error-codes")]
    public List<string> ErrorCodes
    {
        get { return m_ErrorCodes; }
        set { m_ErrorCodes = value; }
    }

    private List<string> m_ErrorCodes;
}

Ответ 9

Использование динамического для проверки recaptcha на стороне сервера

Функция вызова

[HttpPost]
public ActionResult ClientOrderDetail(FormCollection collection, string EncodedResponse)
{
    Boolean Validation = myFunction.ValidateRecaptcha(EncodedResponse);

    return View();
}

Объявление функции

public static Boolean ValidateRecaptcha(string EncodedResponse)
{
    string PrivateKey = "YourSiteKey";

    var client = new System.Net.WebClient();

    var GoogleReply = client.DownloadString(string.Format("https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}", PrivateKey, EncodedResponse));

    var serializer = new JavaScriptSerializer();
    dynamic data = serializer.Deserialize(GoogleReply, typeof(object));

    Boolean Status = data["success"];
    string challenge_ts = data["challenge_ts"];
    string hostname = data["hostname"];

    return Status;
}

Ответ 10

в примере, который я опубликовал в поэтому post использует Newtonsoft.JSON для десериализации полного возвращенного JSON, помещает данные в Google (в отличие от использования querystring) магазинов соответствующие переменные в файле web.config, а не жестко закодированные.

Ответ 11

В этой статье дается четкое пошаговое объяснение того, как реализовать атрибут проверки ReCaptcha в вашей модели.

Сначала создайте атрибут проверки Recaptcha.

namespace Sample.Validation
{
    public class GoogleReCaptchaValidationAttribute : ValidationAttribute
    {
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            Lazy<ValidationResult> errorResult = new Lazy<ValidationResult>(() => new ValidationResult("Google reCAPTCHA validation failed", new String[] { validationContext.MemberName }));

            if (value == null || String.IsNullOrWhiteSpace( value.ToString())) 
            {
                return errorResult.Value;
            }

            IConfiguration configuration = (IConfiguration)validationContext.GetService(typeof(IConfiguration));
            String reCaptchResponse = value.ToString();
            String reCaptchaSecret = configuration.GetValue<String>("GoogleReCaptcha:SecretKey");

            HttpClient httpClient = new HttpClient();
            var httpResponse = httpClient.GetAsync($"https://www.google.com/recaptcha/api/siteverify?secret={reCaptchaSecret}&response={reCaptchResponse}").Result;
            if (httpResponse.StatusCode != HttpStatusCode.OK)
            {
                return errorResult.Value;
            }

            String jsonResponse = httpResponse.Content.ReadAsStringAsync().Result;
            dynamic jsonData = JObject.Parse(jsonResponse);
            if (jsonData.success != true.ToString().ToLower())
            {
                return errorResult.Value;
            }

            return ValidationResult.Success;
        }
    }
}

Затем добавьте атрибут проверки в свою модель.

namespace Sample.Models
{
    public class XModel
    {
        // ...
        [Required]  
        [GoogleReCaptchaValidation]  
        public String GoogleReCaptchaResponse { get; set; }
    }
}

Наконец, вам нужно просто вызвать метод ModelState.IsValid

namespace Sample.Api.Controllers
{
    [ApiController]
    public class XController : ControllerBase
    {
        [HttpPost]
        public IActionResult Post(XModel model)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }
            // ...
        }
    }
}

Эт вуаля! :)