cshtml两个提交按钮发送reCAPTCHA v3 token第二个为空如何解决
问题原因
HTML 要求页面内所有元素 id 必须唯一,你两个表单的 reCAPTCHA token 隐藏域都用了相同的id="token",原生document.getElementById方法只会匹配到第一个符合条件的元素,所以第二个表单的隐藏域始终没有被赋值,提交时后端收到的就是 null。
修复方案
把两个表单的 token 隐藏域去掉重复 id,改用类名标识,再修改 JS 给所有 token 隐藏域统一赋值即可:
1. 修改CSHTML表单代码
@using (Html.BeginForm("myaction", "mycontroller", FormMethod.Post)) { @Html.TextBoxFor(model => model.text) @Html.HiddenFor(model => model.pagenumber) <!-- 替换id为通用类名captcha-token,无需修改name属性 --> <input class="captcha-token" name="token" type="hidden" /> <input type="submit" value="Show comments" /> } @using (Html.BeginForm("myaction", "mycontroller", FormMethod.Post)) { @Html.TextBoxFor(model => model.text) @Html.HiddenFor(model => model.pagenumber) <input class="captcha-token" name="token" type="hidden" /> <input type="submit" value="Show comments" /> }
2. 修改JS赋值逻辑
<script src="https://www.google.com/recaptcha/api.js?render=mysitekey"></script> <script> grecaptcha.ready(function () { grecaptcha.execute('mysitekey', { action: 'submit' }).then(function (token) { // 选中所有带captcha-token类的隐藏域,逐个赋值 document.querySelectorAll('.captcha-token').forEach(item => { item.value = token; }); }); }); </script>
可选优化(避免token过期)
reCAPTCHA v3 生成的 token 有效期只有2分钟,如果用户打开页面很久才提交会触发校验失败,你可以改成表单提交时再实时生成token:
<script> // 给所有表单绑定提交事件 document.querySelectorAll('form').forEach(form => { form.addEventListener('submit', function(e) { // 先阻止默认提交 e.preventDefault(); const currentForm = this; grecaptcha.ready(function () { grecaptcha.execute('mysitekey', { action: 'submit' }).then(function (token) { currentForm.querySelector('.captcha-token').value = token; // 赋值完成后再提交表单 currentForm.submit(); }); }); }); }); </script>
内容的提问来源于stack exchange,提问作者exento
相关产品推荐
相关产品推荐

