reCAPTCHA Enterprise调用创建评估API报400无效参数错误
reCAPTCHA Enterprise 迁移报400 INVALID_ARGUMENT 错误原因及修复方案
问题根因
返回400无效参数不是缺少必填字段,是代码里存在4处参数、格式、逻辑错误:
- 接口鉴权密钥传错:创建Assessment接口URL的
key参数需要传Google Cloud项目下开通了reCAPTCHA Enterprise权限的API密钥,当前代码传的是前端用的RECAPTCHA_SITE_KEY,鉴权参数不合法。 - 字段映射错误:请求体
event.siteKey字段需要传前端集成用的站点密钥(SITE_KEY),代码里错误给这个字段赋值了后端密钥,还因为赋值语句末尾多写了一个逗号,把密钥变量变成了Python单元素元组,不是接口要求的合法字符串格式。 - 请求格式错误:调用
requests.post时用data参数传字典,默认会以application/x-www-form-urlencoded格式提交请求,不会自动序列化为JSON,接口无法解析请求体自然报参数错误。 - 响应校验逻辑是旧版V2的逻辑:reCAPTCHA Enterprise的Assessment接口返回结构没有顶层的
success、error-codes字段,当前的校验逻辑即使请求成功也会抛出异常。
修复步骤
- 前往Google Cloud控制台创建具备reCAPTCHA Enterprise权限的API密钥,替换URL里的密钥参数,不要混用前端站点密钥、旧版V2后端密钥。
- 修正字段映射:
event.siteKey传前端站点密钥,删除赋值语句末尾多余的逗号,避免变量被识别为元组。 - 把
requests.post的data=data改成json=data,自动按JSON格式序列化提交请求。 - 替换响应校验逻辑,按照Enterprise版返回结构判断:先校验
tokenProperties.valid字段确认令牌是否有效,再根据riskAnalysis.score判断风险等级。
修复后的参考代码
import requests from django import forms from django.conf import settings from yourapp import msg # 替换为自身项目的msg模块路径 def verify_captcha_response(self, recaptcha_response): """ 校验reCAPTCHA Enterprise登录场景令牌有效性 """ if not recaptcha_response: return False if isinstance(recaptcha_response, list): recaptcha_response = recaptcha_response[0] # URL中key参数传GCP项目的API密钥,不要用站点密钥/旧版V2密钥 gcp_project_id = "替换为你的GCP项目实际ID" gcp_api_key = settings.RECAPTCHA_GCP_API_KEY # 提前在配置文件中存储GCP API密钥 url = f"https://recaptchaenterprise.googleapis.com/v1/projects/{gcp_project_id}/assessments?key={gcp_api_key}" headers = {'Content-Type': 'application/json'} data = { "event": { "token": recaptcha_response, "siteKey": settings.RECAPTCHA_SITE_KEY, # 此处传前端使用的站点密钥 "expectedAction": "login" } } # 用json参数自动序列化请求体 response = requests.post(url, headers=headers, json=data, timeout=10) result = response.json() # 先判断接口请求本身是否报错 if "error" in result: raise forms.ValidationError(f"验证码校验失败:{result['error']['message']}") # 校验令牌本身有效性 token_properties = result.get("tokenProperties", {}) if not token_properties.get("valid", False): invalid_reason = token_properties.get("invalidReason", "") if invalid_reason in ("TIMEOUT", "DUPLICATE"): raise forms.ValidationError(msg.RECAPTCHA_FAILED) return False # 校验action匹配,防止token被挪用到其他业务场景 if token_properties.get("action") != "login": return False # 根据风险分数判断是否放行:0.0为确定恶意,1.0为确定正常,阈值可根据业务场景调整 risk_score = result.get("riskAnalysis", {}).get("score", 0.0) return risk_score >= 0.5
注意:从reCAPTCHA V2复选框迁移到Enterprise后,不需要再用旧版secret key调用V2的siteverify接口,所有校验逻辑都走Enterprise的assessment接口即可。
内容的提问来源于stack exchange,提问作者Anirudh choudhary
相关产品推荐
相关产品推荐

