ASP.NET 5项目reCaptcha v3在AJAX页面报invalid-input-response错误
问题描述
我正尝试在ASP.NET MVC项目中集成Google reCaptcha v3。该验证在两个页面使用,纯MVC提交的页面运行正常,而用jQuery AJAX提交的页面调用相同验证函数时返回**"invalid-input-response"**错误,但已能从视图获取reCaptcha令牌值。
生成reCaptcha的代码如下
public static IHtmlString ReCaptchaHidden(this HtmlHelper helper) { var mvcHtmlString = new TagBuilder("input") { Attributes = { new KeyValuePair<string, string>("type", "hidden"), new KeyValuePair<string, string>("id", GoogleReCaptchaVariables.InputName), new KeyValuePair<string, string>("name", GoogleReCaptchaVariables.InputName) } }; string renderedReCaptchaInput = mvcHtmlString.ToString(TagRenderMode.Normal); return MvcHtmlString.Create($"{renderedReCaptchaInput}"); } public static IHtmlString ReCaptchaJS(this HtmlHelper helper, string useCase) { string reCaptchaSiteKey = GoogleReCaptchaVariables.ReCaptchaSiteKey; string reCaptchaApiScript = "<script src='https://www.google.com/recaptcha/api.js?render=" + reCaptchaSiteKey + "'></script>"; string reCaptchaTokenResponseScript = "<script>$('form').submit(function(e) { e.preventDefault(); grecaptcha.ready(function() { grecaptcha.execute('" + reCaptchaSiteKey + "', {action: '" + useCase + "'}).then(function(token) { $('#" + GoogleReCaptchaVariables.InputName + "').val(token); $('form').unbind('submit').submit(); }); }); }); </script>"; return MvcHtmlString.Create($"{reCaptchaApiScript}{reCaptchaTokenResponseScript}"); }
验证reCaptcha的代码如下
public string ReCaptchaVerify(string responseToken) { const string apiAddress = "https://www.google.com/recaptcha/api/siteverify"; string recaptchaSecretKey = GoogleReCaptchaVariables.ReCaptchaSecretKey; string responseString = null; var dictionary = new Dictionary<string, string> { { "secret", recaptchaSecretKey }, { "response", responseToken } }; var postContent = new FormUrlEncodedContent(dictionary); using (var httpClient = new HttpClient()) { try { HttpResponseMessage respons = httpClient.PostAsync(apiAddress, postContent).Result; responseString = respons.Content.ReadAsStringAsync().Result; } catch { //Todo: Error handling process goes here } } return responseString; }
解决方法
1. 实时生成AJAX请求的令牌
reCaptcha v3令牌仅单次有效且有效期短,原表单绑定的逻辑适合同步提交,但AJAX场景下易出现令牌过期或重复使用的问题。修改JS逻辑,在AJAX发起前实时获取令牌:
// 替换原表单绑定逻辑,改为AJAX专用提交函数 function submitAjaxForm() { grecaptcha.ready(function() { // 替换为你的站点密钥和业务场景 grecaptcha.execute('你的ReCaptcha站点密钥', {action: 'ajax_submit'}).then(function(token) { $.ajax({ url: '/Controller/Action', // 替换为你的后端接口地址 type: 'POST', data: { // 传递表单其他数据,以及新生成的令牌 responseToken: token, // 其他字段示例:username: $('#username').val() }, success: function(result) { // 处理后端返回结果 console.log(result); }, error: function(xhr) { // 处理错误 } }); }); }); }
2. 确保令牌完整传递
在浏览器控制台打印要传递的令牌值,或在后端ReCaptchaVerify方法开头添加日志,确认responseToken参数是完整的字符串,没有被截断或为空。
3. 添加用户IP参数(优化验证精度)
Google reCaptcha支持传递用户真实IP,缺少该参数可能降低验证通过率。修改后端验证代码:
public string ReCaptchaVerify(string responseToken) { const string apiAddress = "https://www.google.com/recaptcha/api/siteverify"; string recaptchaSecretKey = GoogleReCaptchaVariables.ReCaptchaSecretKey; string responseString = null; var dictionary = new Dictionary<string, string> { { "secret", recaptchaSecretKey }, { "response", responseToken }, // 添加用户IP参数 { "remoteip", System.Web.HttpContext.Current.Request.UserHostAddress } }; var postContent = new FormUrlEncodedContent(dictionary); using (var httpClient = new HttpClient()) { try { HttpResponseMessage respons = httpClient.PostAsync(apiAddress, postContent).Result; responseString = respons.Content.ReadAsStringAsync().Result; } catch { //Todo: Error handling process goes here } } return responseString; }
4. 检查域名权限
登录Google reCaptcha控制台,确认你的项目域名(包括本地开发的localhost:端口号)已添加到允许列表,跨域情况下令牌会被判定无效。
内容的提问来源于stack exchange,提问作者sameer
相关产品推荐
相关产品推荐

