82 votes

Comment mettre en œuvre reCaptcha pour ASP.NET MVC ?

Comment mettre en œuvre reCaptcha dans ASP.NET MVC et C# ?

0 votes

Si vous cherchez la dernière solution pour combiner Google reCAPTCHA v2 & v3 dans ASP.NET Web Forms, consultez cette démo. techtolia.com/Recaptcha

84voto

George Stocker Points 31258

Il existe quelques bons exemples :

Ce sujet a également été traité auparavant dans cette question de Stack Overflow .

NuGet Google reCAPTCHA V2 pour MVC 4 et 5

0 votes

Merci pour cette réponse rapide. J'ai une question, qui a créé Recaptcha.dll ? L'équipe de Google ?

4 votes

ReCaptcha a été créé par un professeur de l'université d'Amsterdam. Université Carnegie Mellon Je crois.

1 votes

Le troisième ( dotnetcurry.com/ShowArticle.aspx?ID=611 ) a bien fonctionné pour moi.

33voto

Magpie Points 1743

J'ai ajouté reCaptcha à un projet sur lequel je travaille actuellement. J'avais besoin qu'il utilise l'API AJAX car l'élément reCaptcha était chargé dynamiquement dans la page. Je n'ai pas trouvé de contrôles existants et l'API est simple, j'ai donc créé le mien.

Je vais poster mon code ici au cas où quelqu'un le trouverait utile.

1 : Ajouter la balise script aux en-têtes de la page principale

<script type="text/javascript" src="http://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>

2 : Ajoutez vos clés au web.config

<appSettings>
    <add key="ReCaptcha.PrivateKey" value="[key here]" />
    <add key="ReCaptcha.PublicKey" value="[key here]" />
</appSettings>

3 : Créer l'attribut Action et les extensions Html Helper

namespace [Your chosen namespace].ReCaptcha
{
    public enum Theme { Red, White, BlackGlass, Clean }

    [Serializable]
    public class InvalidKeyException : ApplicationException
    {
        public InvalidKeyException() { }
        public InvalidKeyException(string message) : base(message) { }
        public InvalidKeyException(string message, Exception inner) : base(message, inner) { }
    }

    public class ReCaptchaAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            var userIP = filterContext.RequestContext.HttpContext.Request.UserHostAddress;

            var privateKey = ConfigurationManager.AppSettings.GetString("ReCaptcha.PrivateKey", "");

            if (string.IsNullOrWhiteSpace(privateKey))
                throw new InvalidKeyException("ReCaptcha.PrivateKey missing from appSettings");

            var postData = string.Format("&privatekey={0}&remoteip={1}&challenge={2}&response={3}",
                                         privateKey,
                                         userIP,
                                         filterContext.RequestContext.HttpContext.Request.Form["recaptcha_challenge_field"],
                                         filterContext.RequestContext.HttpContext.Request.Form["recaptcha_response_field"]);

            var postDataAsBytes = Encoding.UTF8.GetBytes(postData);

            // Create web request
            var request = WebRequest.Create("http://www.google.com/recaptcha/api/verify");
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";
            request.ContentLength = postDataAsBytes.Length;
            var dataStream = request.GetRequestStream();
            dataStream.Write(postDataAsBytes, 0, postDataAsBytes.Length);
            dataStream.Close();

            // Get the response.
            var response = request.GetResponse();

            using (dataStream = response.GetResponseStream())
            {
                using (var reader = new StreamReader(dataStream))
                {
                    var responseFromServer = reader.ReadToEnd();

                    if (!responseFromServer.StartsWith("true"))
                        ((Controller)filterContext.Controller).ModelState.AddModelError("ReCaptcha", "Captcha words typed incorrectly");
                }
            }
        }
    }

    public static class HtmlHelperExtensions
    {
        public static MvcHtmlString GenerateCaptcha(this HtmlHelper helper, Theme theme, string callBack = null)
        {
            const string htmlInjectString = @"<div id=""recaptcha_div""></div>
<script type=""text/javascript"">
    Recaptcha.create(""{0}"", ""recaptcha_div"", {{ theme: ""{1}"" {2}}});
</script>";

            var publicKey = ConfigurationManager.AppSettings.GetString("ReCaptcha.PublicKey", "");

            if (string.IsNullOrWhiteSpace(publicKey))
                throw new InvalidKeyException("ReCaptcha.PublicKey missing from appSettings");

            if (!string.IsNullOrWhiteSpace(callBack))
                callBack = string.Concat(", callback: ", callBack);

            var html = string.Format(htmlInjectString, publicKey, theme.ToString().ToLower(), callBack);
            return MvcHtmlString.Create(html);
        }
    }
}

4 : Ajoutez le captcha à votre vue

@using (Html.BeginForm("MyAction", "MyController"))
{
   @Html.TextBox("EmailAddress", Model.EmailAddress)
   @Html.GenerateCaptcha(Theme.White)
   <input type="submit" value="Submit" />
}

5 : Ajoutez l'attribut à votre action

[HttpPost]
[ReCaptcha]
public ActionResult MyAction(MyModel model)
{
   if (!ModelState.IsValid) // Will have a Model Error "ReCaptcha" if the user input is incorrect
      return Json(new { capthcaInvalid = true });

   ... other stuff ...
}

6 : Notez que vous devrez recharger le captcha après chaque message, même s'il était valide et qu'une autre partie du formulaire était invalide. Utilisez Recaptcha.reload();

0 votes

Est-il possible avec ce code de n'annoter ReCaptcha qu'après 5 échecs de connexion ?

2 votes

Si vous mettez en œuvre cette solution, tenez compte du fait que la nouvelle URL de l'API est la suivante : google.com/recaptcha/api/siteverify ( source )

7voto

Chase Florell Points 18248

J'ai implémenté avec succès ReCaptcha de la manière suivante.
note : ceci est en VB, mais peut facilement être converti

1] Tout d'abord, prenez une copie de la Bibliothèque reCaptcha

2] Créez ensuite un assistant HTML ReCaptcha personnalisé.

    ''# fix SO code coloring issue.
    <Extension()>
    Public Function reCaptcha(ByVal htmlHelper As HtmlHelper) As MvcHtmlString
        Dim captchaControl = New Recaptcha.RecaptchaControl With {.ID = "recaptcha",
                                                                  .Theme = "clean",
                                                                  .PublicKey = "XXXXXX",
                                                                  .PrivateKey = "XXXXXX"}
        Dim htmlWriter = New HtmlTextWriter(New IO.StringWriter)
        captchaControl.RenderControl(htmlWriter)
        Return MvcHtmlString.Create(htmlWriter.InnerWriter.ToString)
    End Function

3] A partir de là, vous avez besoin d'un validateur côté serveur réutilisable.

Public Class ValidateCaptchaAttribute : Inherits ActionFilterAttribute
    Private Const CHALLENGE_FIELD_KEY As String = "recaptcha_challenge_field"
    Private Const RESPONSE_FIELD_KEY As String = "recaptcha_response_field"

    Public Overrides Sub OnActionExecuting(ByVal filterContext As ActionExecutingContext)

        If IsNothing(filterContext.HttpContext.Request.Form(CHALLENGE_FIELD_KEY)) Then
            ''# this will push the result value into a parameter in our Action
            filterContext.ActionParameters("CaptchaIsValid") = True
            Return
        End If

        Dim captchaChallengeValue = filterContext.HttpContext.Request.Form(CHALLENGE_FIELD_KEY)
        Dim captchaResponseValue = filterContext.HttpContext.Request.Form(RESPONSE_FIELD_KEY)

        Dim captchaValidtor = New RecaptchaValidator() With {.PrivateKey = "xxxxx",
                                                                       .RemoteIP = filterContext.HttpContext.Request.UserHostAddress,
                                                                       .Challenge = captchaChallengeValue,
                                                                       .Response = captchaResponseValue}

        Dim recaptchaResponse = captchaValidtor.Validate()

        ''# this will push the result value into a parameter in our Action
        filterContext.ActionParameters("CaptchaIsValid") = recaptchaResponse.IsValid

        MyBase.OnActionExecuting(filterContext)
    End Sub

au-dessus de cette ligne est un code réutilisable **Une seule fois**.


sous cette ligne, on voit à quel point il est facile de mettre en œuvre reCaptcha encore et encore

Maintenant que vous avez votre code réutilisable... tout ce que vous devez faire est d'ajouter le captcha à votre vue.

<%: Html.reCaptcha %>

Et quand vous envoyez le formulaire à votre contrôleur...

    ''# Fix SO code coloring issues
    <ValidateCaptcha()>
    <AcceptVerbs(HttpVerbs.Post)>
    Function Add(ByVal CaptchaIsValid As Boolean, ByVal [event] As Domain.Event) As ActionResult

        If Not CaptchaIsValid Then ModelState.AddModelError("recaptcha", "*")

        '#' Validate the ModelState and submit the data.
        If ModelState.IsValid Then
            ''# Post the form
        Else
            ''# Return View([event])
        End If
    End Function

0 votes

Note : ceci est en VB mais peut facilement être converti en C#

1 votes

Merci beaucoup d'avoir élaboré la solution. C'est une réponse très détaillée. Je l'adore.

1 votes

D'après le dernier blog de Joel, les créateurs de StackOverflow veulent que ce soit une Dépôt Wiki au lieu de simplement rediriger les utilisateurs vers d'autres sites. Vous renvoyer vers un site peut répondre à votre question aujourd'hui, mais ne résoudra pas le problème de quelqu'un d'autre lorsque cette page externe tombera l'année prochaine. Publier la bonne réponse ici aidera également les futurs demandeurs. Je pense que c'est la bonne façon de répondre à une question.

1voto

Derrick Points 890

Il y a une belle mise en œuvre ici : RecaptchaControlMvc.cs

1voto

Pat Points 11

Pour tous ceux qui cherchent, voici une série d'étapes décentes. http://forums.asp.net/t/1678976.aspx/1

N'oubliez pas d'ajouter manuellement votre clé dans OnActionExecuting() comme je l'ai fait.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X