webentwicklung-frage-antwort-db.com.de

Überprüfung von Recaptcha 2 (Kein CAPTCHA reCAPTCHA) auf der Serverseite von ASP.NET

Das neue Recaptcha 2 sieht vielversprechend aus, aber ich habe keinen Weg gefunden, es auf ASP-Server-Server zu überprüfen.

if(Page.IsValid) in Diese Antwort gilt für das alte Recaptcha, nicht jedoch für das neue,

Wie validiere ich das neue reCAPTCHA auf der Serverseite?

64
Alaa

Nachdem ich viele Ressourcen gelesen hatte, schrieb ich diese Klasse, um die Validierung von des neuen ReCaptcha zu handhaben:

Here : Wenn ein reCAPTCHA vom Endbenutzer gelöst wird, wird ein neues Feld (g-recaptcha-response) in HTML eingefügt.

Wir müssen diesen Wert lesen und an die nachfolgende Klasse übergeben, um ihn zu bestätigen:

In c #:

Im Code hinter Ihrer Seite:

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

if (IsCaptchaValid) {
    //Valid Request
}

Die Klasse:

  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;
    }

In VB.NET:

Im Code hinter Ihrer Seite:

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

Die Klasse:

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
135
Alaa

Hier ist eine Version, die den JavaScriptSerializer verwendet. Danke Ala für die Basis für diesen Code.

WebConfig App Setting - Ich habe in meinem Fall den geheimen Schlüssel zur Web.Config hinzugefügt, um Transformationen zwischen Umgebungen zu ermöglichen. Sie kann hier auch bei Bedarf einfach verschlüsselt werden.

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

Die ReCaptcha-Klasse - Eine einfache Klasse, um den Antwortparameter zusammen mit Ihrem Geheimnis an Google zu senden und zu validieren. Die Antwort wird mit der .Net JavaScriptSerializer-Klasse deserialisiert und von dieser zurückgegeben.

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;
    }
}

Validate The Response - Überprüfen Sie die Gültigkeit des Formularparameters g-Recaptcha-Response in Ihrem Controller (oder den Code dahinter für ein Webformular), und ergreifen Sie die entsprechenden Maßnahmen.

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
}   
39
Paul

Die meisten dieser Antworten erscheinen komplexer als nötig. Sie geben auch nicht die IP-Adresse an, mit der ein Abfangangriff verhindert werden kann ( https://security.stackexchange.com/questions/81865/is-there-any-reason-to-include-the-remote-ip-hen- using-recaptcha ). Hier ist was ich beschlossen habe

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"];
    }
}
12
Luke McGregor

Sie können die Methode "IsValidCaptcha ()" verwenden, um Ihr Google Recaptcha auf Serverseite zu überprüfen. Ersetzen Sie Ihren geheimen Schlüssel durch "YourRecaptchaSecretkey" in der folgenden Methode.

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;
 }

Erstellen Sie auch folgende Klasse.

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

Referenz Link

6
Tabish Usman

Hier ist meine Lösung von Ala's Lösung, um:

  • parameter in POST senden
  • um die Formulareingabe zu bereinigen
  • geben Sie die IP-Adresse des Anforderers ein
  • speichern Sie das Geheimnis in Web.Config:

Im Controller:

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

Die Nutzenklasse: 

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;
        }
    }       
}
3

Laut doc geben Sie einfach Ihren geheimen Schlüssel und die Antwort des Benutzers an die API an und lesen die zurückgegebene Eigenschaft "success"

KURZE ANTWORT:

        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!!!

VOLLSTÄNDIGES BEISPIEL

Angenommen, Sie implementieren this page in 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>

Angenommen, Sie möchten, dass der Controller gespeichert wird, sagen wir "I_AM_NOT_ROBOT" in der Sitzung, wenn die Überprüfung erfolgreich war:

    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");
    }
3
epox

Ein weiteres Beispiel ist hier veröffentlicht:

RecaptchaV2.NET (Github)

Es implementiert auch die sichere Token-Option von Recaptcha 2.0 (siehe vollständigen Quellcode für dieses Bit, ich habe relevante Teile NUR für die Validierung eines Ergebnisses entfernt).

Dieser setzt nicht auf den Json-Parser von Newtonsoft und verwendet stattdessen den in .NET eingebauten.

Hier ist der relevante Codeausschnitt aus der Bibliothek RecaptchaV2.NET (von 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());
    }
  }
}
1
Matt

Die ReCaptcha-API von Google akzeptiert die Nutzdaten nicht mehr als Abfragezeichenfolgeparameter in einer GET-Anforderung. Google hat immer eine "falsche" Antwort zurückgegeben, es sei denn, ich habe die Daten per HTTP-POST gesendet. Hier ist ein Update der Klasse Ala (ausgezeichnet!), Die die Nutzdaten an den Google-Service-Endpunkt POST stellt:

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;
}
1
Justin Gould

Verwendung von Dynamic zur Validierung von Recaptcha auf Serverseite

Funktion aufrufen

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

    return View();
}

Funktionserklärung

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;
}
0
Arun Prasad E S

das Beispiel, das ich in this so post veröffentlicht habe, verwendet Newtonsoft.JSON, um die vollständig zurückgegebene JSON zu deserialisieren, bucht die Daten bei Google (statt mit einer Querzeichenfolge) und speichert die relevanten Variablen in der web.config und nicht hart codiert.

0
Brent

Dieser Artikel Erklären Sie Schritt für Schritt, wie Sie ein ReCaptcha-Validierungsattribut in Ihrem Modell implementieren.

Erstellen Sie zunächst das Validierungsattribut 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;
        }
    }
}

Fügen Sie dann das Validierungsattribut zu Ihrem Modell hinzu.

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

Schließlich müssen Sie nur noch die ModelState.IsValid-Methode aufrufen

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

Et voilà! :)

0
rdhainaut