简体   繁体   中英

Google reCaptcha Not Working

I'm writing because no question on this site has truly helped me figure out why reCaptcha isn't getting verified. I'm using two reCaptcha's V2 and Invisible on my page. Unfortunately, the project I'm working with is very old and while it looks like it's ASP.NET MVC, I don't see any controllers or models, so I have no idea what it really was written in. I'm rebuilding the project in ASP.NET WebForms, and I have reCaptcha working in it perfectly. The problem is that I have to use JavaScript for the old site until I get the new site published which won't be for several more months.

Here is my form:

<form id="form" action="?" method="post">
<fieldset>

    <div class="form-group">
        <div class="row">
            <div class="col-md-12">

                @* RECAPTCHA V2 WIDGET *@
                <div id="captcha2" class="g-recaptcha"
                     data-sitekey="6LdOZWkUAAAAAE1EhMyhMPF5IwM3lflaeyZ2VWaB"></div>
                <br />
                @* MESSAGE FROM RECAPTCHA *@
                <div id="msg" class="msg-error error"></div>
                <br>
                @* SUBMIT BUTTON FOR VALIDATION & RECAPTCHA *@
                <input id="submit" type="submit" name="buttonSubmit" class="btn btn-success btn-large"
                       value="Submit Information Request" />
                <input type="hidden" name="registerDate" value="@DateTime.Now" />
            </div>
        </div>
    </div>

    @* RECAPTCHA INVISIBLE WIDGET *@
    <div id="captchaI" class="g-recaptcha"
         data-sitekey="6LduaWkUAAAAAHp0EU5JXdTIszKR-g2AZfDqmLiv"
         data-callback="submit"
         data-size="invisible">
    </div>
</fieldset>

Here is my JavaScript:

<script>
$('#submit').click(function () {
    //var obj =
    //{
    //    secret: "MY_PRIVATE_KEY",
    //    response: grecaptcha.getResponse()
    //};
    //var json = JSON.stringify(obj);
    //window.location = "https://www.google.com/recaptcha/api/siteverify?" + json;

    //var respJSON = '{"success": true | false, "challenge_ts": timestamp, "hostname":string}';
    //var respObj = JSON.parse(respJSON);
    //alert(respObj.success + "\n" + respObj.challenge_ts + "\n" + respObj.hostname);

    //--------------------------------------------------------------------

    alert("NO JSON\n" + grecaptcha.getResponse()); //I GET A HASHED RESPONSE

    var response = grecaptcha.getResponse();
    var stringy = JSON.stringify("STRINGIFY\n" + response);
    alert(stringy); //I GET A HASHED RESPONSE
    var parsy = JSON.parse("PARSED" + response);
    alert(parsed);  //I GET NOTHING

    //--------------------------------------------------------------------

    //var pk = 'MY_PRIVATE_KEY';
    //var url = "https://www.google.com/recaptcha/api/siteverify?secret=";
    //$.post(url,
    //    {
    //        "secret": pk,
    //        "response": "&response=" + response
    //    },
    //    function (response) {
    //        alert(response);
    //    });

    //alert(response);
    //JSON.stringify(response);
    //alert(response);
    //$('#msg').prepend(response);
    //if (!response) {
    //    $('#msg').text("No Response from Captcha.");
    //}
});

As you can see I'm using jQuery with JSON. I've tried to pull the response from the reCaptcha in numerous ways, usually posting messages in the #msg div, but nothing ever gets displayed there.

I know what the Google Developers reCaptcha Guide says, but it is less than helpful on how to actually implement this. Please help as no other solution either verifies the response with siteverify, uses PHP which I cannot use due to agency controls, or as in the case of the Developers Guide, is less than helpful.

It looks like your trying to verify the response client side. That won't work. Google will only verify response sent from the url you registered with them. So you need to verify the response server side.

First, get the hashed code from the widget

var captchaResponse = window.grecaptcha.getResponse();
if (captchaResponse === "") {
    alert("Please check \"I'm not a robot'\"");
    return;
}

Next, send the response to your server.

$.ajax({
    type: "POST",
    url: newRequestUrl,
    crossDomain: true,
    xhrFields: {
        withCredentials: false
    },
    data: {
        request: JSON.stringify(request),
        recaptchaResponse: recaptchaResponse
    },
    error: function (x1, x2, x3, x4) {
        alert("Error: unable to process request");
        window.grecaptcha.reset();
    },
    success: function (respose) {
        window.grecaptcha.reset();

        alert("Request received");
    }
});

For my purposes, I need to post cross domain. You can probably remove the crossDomain parameter.

Then, here's my end point to handle the post. Depending on your projects state you may need to use classic ASP.NET forms for this instead.

    [AllowAnonymous]
    public JsonResult NewRequest(string request, string recaptchaResponse)
    {
        if (VerifyRecaptchaResponse(recaptchaResponse, Request.UserHostAddress) == false)
        {
            return Json(new { Error = "Invalid reCAPTCHA response" });
        }

        return Json(true);
    }

Last, verify the response.

    private static bool VerifyRecaptchaResponse(string recaptchaResponse, string remoteIp)
    {
        var recaptchaApiUrl = ConfigurationManager.AppSettings["recaptchaApiUrl"];
        var secret = ConfigurationManager.AppSettings["recaptchaSecretKey"];
        var postData = string.Format(CultureInfo.InvariantCulture, "&secret={0}&remoteip={1}&response={2}", secret, remoteIp, recaptchaResponse);
        var postDataAsBytes = Encoding.UTF8.GetBytes(postData);

        var request = WebRequest.Create(recaptchaApiUrl);
        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();

        var response = request.GetResponse();

        using (var stream = response.GetResponseStream())
        {
            if (stream == null) return false;

            using (var reader = new StreamReader(stream))
            {
                var serializer = new JavaScriptSerializer();
                var text = reader.ReadToEnd();
                var responseFromServer = serializer.DeserializeObject(text) as Dictionary<string, object>;
                if (responseFromServer == null) return false;
                if (responseFromServer.ContainsKey("success") == false) return false;
                if (responseFromServer["success"] is bool == false) return false;

                return (bool)responseFromServer["success"];
            }
        }
    }

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM