在.NET Web API+Angular集成Google reCAPTCHA v3时遇invalid-input-response错误
Google reCAPTCHA v3集成问题:invalid-input-response错误
我正在将Google reCAPTCHA v3集成到.NET后端(ASP.NET Core)与Angular前端项目中。后端已实现captchaTokenVerify方法,通过Google reCAPTCHA API验证令牌,但收到返回结果:
{ "success": false, "error-codes": ["invalid-input-response"] }
前后端配置
.NET后端代码
public async Task<DataTable> captchaTokenVerify(string secret, string siteToken) { DataTable dt = new DataTable(); dt.Columns.Add("Success", typeof(bool)); dt.Columns.Add("Score", typeof(decimal)); dt.Columns.Add("ErrorMessage", typeof(string)); try { var values = new Dictionary<string, string> { { "secret", secret }, { "response", siteToken } }; var content = new FormUrlEncodedContent(values); var response = await client.PostAsync("https://www.google.com/recaptcha/api/siteverify", content); response.EnsureSuccessStatusCode(); var responseString = await response.Content.ReadAsStringAsync(); var json = JObject.Parse(responseString); bool success = json["success"].Value<bool>(); decimal score = json.ContainsKey("score") ? json["score"].Value<decimal>() : 0; string errorMessage = success ? null : json["error-codes"]?.ToString(); dt.Rows.Add(success, score, errorMessage); return dt; } catch (Exception ex) { dt.Rows.Add(false, 0, $"Error: {ex.Message}"); return dt; } }
Angular前端代码
// Angular service captchaTokenVerify(token: string) { console.log('tok', token); return this.http.get<any>(`${this.getBaseUrl()}Auth/captchaTokenVerify?secret=${environment.CAPTCHA_SECRET_KEY_V3}&siteToken=${token}`); } // Triggering reCAPTCHA verification executeRecaptchaV3() { this.recaptchaV3Service.execute(environment.CAPTCHA_SECRET_KEY_V3, 'myAction', (token) => { this.authService.captchaTokenVerify(token).subscribe({ next: (res) => { console.log('res', res); }, error: (err) => { this.notification.showError('Oops!', validateForm.getErrorMessage(err)); }, }); }); }
已尝试的排查步骤
- 验证令牌:确认前端通过
recaptchaV3Service.execute生成了有效令牌 - 编码格式:后端使用
FormUrlEncodedContent确保数据为application/x-www-form-urlencoded格式 - 密钥校验:确认使用的是Google reCAPTCHA控制台中的正确密钥
疑问
- 引发
invalid-input-response错误的可能原因是什么? - 前后端配置中是否存在遗漏环节导致该错误?
问题分析与解决方案
1. invalid-input-response错误的常见原因
- 令牌过期:reCAPTCHA v3令牌有效期仅2分钟,超时验证会触发该错误
- 令牌无效/重复使用:令牌被篡改、重复提交,或不是由对应站点密钥生成
- 密钥不匹配:后端用的密钥与前端生成令牌的站点密钥不配对(比如混用v2/v3密钥,或站点密钥和密钥搞反)
- 参数传递错误:
response参数未传递完整令牌,或存在编码异常 - 服务器访问限制:你的服务器IP被Google临时限制,无法正常发起验证请求
2. 你的代码中存在的关键问题
- 前端
execute方法参数错误:recaptchaV3Service.execute的第一个参数应该是站点密钥(site key),你现在传的是密钥(secret key),导致生成的令牌本身无效 - GET请求暴露密钥:将密钥拼在URL参数中传递,会泄露敏感信息,同时可能被Google判定为异常请求
- 后端返回DataTable设计不合理:增加前后端解析复杂度,建议改用强类型DTO
修复步骤
修正前端令牌生成逻辑:
替换execute方法的第一个参数为站点密钥:executeRecaptchaV3() { // 使用站点密钥而非密钥 this.recaptchaV3Service.execute(environment.CAPTCHA_SITE_KEY_V3, 'myAction', (token) => { this.authService.captchaTokenVerify(token).subscribe({ next: (res) => console.log('res', res), error: (err) => this.notification.showError('Oops!', validateForm.getErrorMessage(err)) }); }); }修改前端API请求方式:
改用POST请求,仅传递令牌,密钥由后端从配置读取:// Angular service captchaTokenVerify(token: string) { console.log('tok', token); return this.http.post<any>(`${this.getBaseUrl()}Auth/captchaTokenVerify`, { token }); }更新后端代码:
从配置读取密钥,改用强类型DTO接收和返回数据:// 定义返回结果DTO public class CaptchaVerifyResult { public bool Success { get; set; } public decimal Score { get; set; } public string ErrorMessage { get; set; } } // 接收请求的DTO public class CaptchaVerifyRequest { public string Token { get; set; } } [HttpPost] public async Task<CaptchaVerifyResult> CaptchaTokenVerify([FromBody] CaptchaVerifyRequest request) { try { // 从配置读取密钥,禁止前端传递 var secret = _configuration["Captcha:SecretKeyV3"]; var values = new Dictionary<string, string> { { "secret", secret }, { "response", request.Token } }; var content = new FormUrlEncodedContent(values); var response = await _httpClient.PostAsync("https://www.google.com/recaptcha/api/siteverify", content); response.EnsureSuccessStatusCode(); var responseString = await response.Content.ReadAsStringAsync(); var json = JObject.Parse(responseString); bool success = json["success"].Value<bool>(); decimal score = json.ContainsKey("score") ? json["score"].Value<decimal>() : 0; string errorMessage = success ? null : string.Join(", ", json["error-codes"].Values<string>()); return new CaptchaVerifyResult { Success = success, Score = score, ErrorMessage = errorMessage }; } catch (Exception ex) { return new CaptchaVerifyResult { Success = false, Score = 0, ErrorMessage = $"Error: {ex.Message}" }; } }额外校验项:
- 确认后端用的是reCAPTCHA v3的密钥,前端用的是对应的站点密钥
- 确保令牌生成后立即发起验证,避免过期
- 检查服务器是否能正常访问Google验证API,无防火墙/代理拦截
内容的提问来源于stack exchange,提问作者Clinton Hadrian
相关产品推荐
相关产品推荐

