Laravel 8身份验证后提交表单出现CSRF Token Mismatch问题求助
Laravel 8注册流程中CSRF Token不匹配问题
在Laravel 8开发的注册流程里,用户选择不同账户类型后会弹出窗口完成手机身份验证。验证通过后弹窗关闭,自动提交POST方法的certForm表单跳转到对应注册页(用POST是为了防止未验证直接访问注册页),但此时触发了CSRF token mismatch错误。
相关代码
后端Livewire代码
public function verify(Request $request) { $identityVerification = new IdentityVerification(); $iv = $identityVerification->verify($request->post()); if($iv["Resultcd"] == "0000") { echo "<script>window.opener.document.getElementById('cert').value = 'ok';</script>"; echo "<script>alert('DONE.');</script>"; echo "<script>window.opener.document.certForm.submit();</script>"; echo "<script>window.close();</script>"; } else { echo "<script>alert('FAILED');</script>"; echo "<script>location.href = '/login';</script>"; } } public function render() { return view('livewire.register-type'); }
前端视图代码
<div> <?php $Siteurl = "Crack.com"; ... some Code ?> <div> <main style="display: flex; flex-direction: column; justify-content: center; align-items: center; height: 100vh;"> <div> <div> <p style="text-align: center; font-size: 1.5rem;">start</p> </div> </div> <div style="display: flex; gap: 1rem; text-align: center; margin-top: 2rem;"> <div> <div style="row-gap: 3rem; height: 100%; padding: 1rem; border: 1px solid rgb(110 174 211); border-radius: 1rem; display: flex; flex-direction: column; justify-content: center;"> <a href="javascript:verifyNumber('/register-school');"> <div style="display: flex; justify-content: space-around; align-items: center; padding: 1rem; background-color: rgb(110 174 211);"> <span> This Button </span> <img src="/assets/img/tap.png" width="40"> </div> </a> </div> </div> <div> <div style="row-gap: 3rem; height: 100%; padding: 1rem; border: 1px solid rgb(235 185 185); border-radius: 1rem; display: flex; flex-direction: column; justify-content: center;"> <a href="javascript:verifyNumber('/register-company');"> <div onclick="" style="display: flex; justify-content: space-around; align-items: center; padding: 1rem; background-color: rgb(235 185 185);"> This Button 222 </span> <img src="/assets/img/tap.png" width="40"> </div> </a> </div> </div> </div> </main> </div> ... some Code <form name="payForm" accept-charset='euc-kr' method="GET"> @csrf ... some Code <input type="hidden" name="Siteurl" id="Siteurl" value="{{$Siteurl ?? ''}}"> <input type="hidden" name="type" id="type" value=""> <input type="hidden" name="route" id="route" value=""> <input type="hidden" name="_token" value="{{ csrf_token() }}"> </form> <form method="post" name="certForm"> @csrf <input type="hidden" name="cert" id="cert" value=""> <input type="hidden" name="_token" value="{{ csrf_token() }}"> </form> <script> function verifyNumber(route) { document.certForm.action = route; PAYMENT(document.payForm); } </script> </div>
已尝试的方案
- 为各注册页添加身份验证功能,但弹窗关闭后一段时间会出现页面过期提示
- 修改certForm的提交方法,但无法保证必须验证的逻辑
- 修改验证过期后的回调URL,问题依旧
- 查询CSRF token过期与刷新机制,但未理解
问题原因及解决方案
核心原因
- Token过期或字段冲突:弹窗验证耗时较长时,原页面的CSRF Token可能过期;同时
certForm里重复添加了_token字段(@csrf指令已自动生成,又手动加了一次),导致表单提交时Token值混乱。 - Session上下文不一致:弹窗页面若未和父页面共享Session,会导致提交的Token与Laravel存储的Session Token不匹配。
解决步骤
步骤1:清理重复的Token字段
删除certForm里手动添加的_token输入框,只保留@csrf指令,避免字段冲突:
<form method="post" name="certForm"> @csrf <input type="hidden" name="cert" id="cert" value=""> </form>
步骤2:提交前刷新Token
由于弹窗验证可能耗时较久,原页面Token容易过期,修改后端验证成功的脚本,先获取父页面最新的Token再提交:
// 替换verify方法里的成功脚本 echo "<script> window.opener.document.getElementById('cert').value = 'ok'; // 从父页面meta标签获取最新CSRF Token并更新表单 const metaToken = window.opener.document.querySelector('meta[name=\"csrf-token\"]').content; const tokenInput = window.opener.document.certForm.querySelector('input[name=\"_token\"]'); if(tokenInput) tokenInput.value = metaToken; alert('DONE.'); window.opener.document.certForm.submit(); window.close(); </script>";
确保父页面头部存在CSRF meta标签(Laravel默认已包含,缺失则添加):
<meta name="csrf-token" content="{{ csrf_token() }}">
步骤3:保证Session一致性
弹窗必须通过父页面的window.open()打开,而非直接跳转外部链接,这样才能维持和父页面相同的Session上下文,避免Token不匹配。
备选方案:使用一次性验证令牌
若上述方法仍有问题,可在验证通过后生成一个一次性令牌(存储在Session或Redis中),通过certForm提交该令牌,注册页验证令牌有效性而非依赖CSRF Token,既保证验证逻辑,又避开Token过期问题。
内容的提问来源于stack exchange,提问作者C Hy
相关产品推荐
相关产品推荐

