You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

新窗口提交表单时CSRF令牌验证失败问题求助

问题

以下是我编写的代码:

<body>
    <form:form id="gotoPopupPreview" name="gotoPopupPreview" method="post" action="">
        <input type="hidden" name="isPreview" value="Y">
        <input type="hidden" name="nttId" value="${searchVO.nttId}">
        <!--...(skip)-->
    </form:form>

    <script>
        function openPreview(url, target, otherData){
        var f = $("#gotoPopupPreview");
        f.attr('action', url);
        f.attr('target', target);
    //...(skip)
        window.open('', target);
        f.submit();
    }

    $("#submitBtn").click(function(){
        var otherData = 'blahblah';
        openPreview("http://www.test.or.kr/", 'test', otherData);
    });
    </script>
</body>

执行后服务器返回错误:

AccessDeniedException : org.springframework.security.web.csrf.MissingCsrfTokenException: Could not verify the provided CSRF token because your session was not found.
result :::: {"result" : "fail", "message" : "Could not verify the provided CSRF token because your session was not found."}

我确认JSP form标签库已自动添加CSRF令牌,页面源码也能看到该字段,但仍出现异常。请问是否是新窗口提交导致的问题?这种情况下该如何正确传递CSRF令牌?

解答

问题确实出在提前打开新窗口的操作上:

  • 先执行window.open('', target)创建空白窗口时,这个新窗口会生成一个全新的会话(或未关联原页面的会话)。
  • 随后提交原页面表单时,表单携带的CSRF令牌属于原页面的会话,服务器在新窗口的会话中找不到对应的令牌记录,因此抛出异常。

解决方案

最简洁有效的修复方式是移除提前打开窗口的代码,直接提交表单:

function openPreview(url, target, otherData){
    var f = $("#gotoPopupPreview");
    f.attr('action', url);
    f.attr('target', target);
    // 去掉window.open('', target);这一行
    f.submit();
}

浏览器会在表单提交时自动创建指定target的新窗口,此时新窗口的会话会和表单提交的请求自动关联,CSRF令牌验证就能正常通过。

额外注意事项

  1. 确保目标URL和当前页面处于同域:跨域场景下Spring Security的CSRF机制本身不生效,若需跨域提交要改用其他方案。
  2. 确认form:form生成的CSRF字段正确:默认情况下Spring Security会生成名为_csrf的隐藏域,你可以在页面源码中检查是否存在类似<input type="hidden" name="_csrf" value="xxx">的字段。

内容的提问来源于stack exchange,提问作者sinichee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 15:32:46