【问题标题】:Listen to all form submit events and perform a function before any other attached event handlers侦听所有表单提交事件并在任何其他附加事件处理程序之前执行功能
【发布时间】:2011-12-10 03:04:08
【问题描述】:

我正在尝试在现有的大型 Web 应用程序中防止 CSRF 攻击。我选择了一个使用 JS 注入任何形式的令牌和一个 Java Servlet 过滤器,该过滤器将在允许请求继续之前检查它的存在。首先,我们很高兴要求用户拥有 JS。

其次 - 我该怎么做?

最简单的想法:$(document).live("submit", myTokenAddFn); 行不通。

事实证明,令牌注入部分非常棘手,因为正如我所说,Web 应用程序非常庞大,并且需要跨越许多桥梁:

  • 有些表单是在页面加载后创建的(使用 JS)
  • 我们使用 JSF(在锚标签上有 onclick 属性来提交表单)
  • 有使用 AJAX 提交 jQuery 表单的实例
  • 已经有很多 onclick 处理程序附加到表单提交元素

我觉得我非常接近,但我不敢相信我不会影响速度较慢的浏览器的性能。我开始认为可能有更好的方法。

我做了什么:

  • 克服 jQuery AJAX 表单提交问题: 在发送 AJAX 请求之前,使用ajaxSend 方法将我的令牌附加到真实数据值
  • 要将令牌添加到页面加载时页面上的简单表单元素: 在页面加载时有效地循环表单并添加令牌,然后添加表示此表单具有令牌的 jQuery data (以提高下一步的性能)
  • 克服动态创建的表单:$("input[type='submit'],input[type='image'],button,a[onclick]").live("mousedown", myTokenAddFn); 上面的行处理了很多问题,“myTokenAddFn”实际上只是再次循环浏览页面,寻找所有没有我在页面加载时添加的 jQuery 数据项的表单。 它处理使用锚标记的 onclick 属性提交的 JSF 表单,不驻留在表单中但提交表单的按钮,并确保始终在任何其他 onclick 处理程序提交表单(可能存在)之前添加令牌.

最新一期:

一个 JS 表单被动态添加到页面中,当光标在输入文本字段中时,用户使用 enter 键提交它。用户(感谢我的 Java Servlet)已注销。

最简单的解决方法是将按键侦听器包含到所有输入元素,但这里的性能让我担心。

有什么建议吗?重新开始的想法?

提前致谢。

【问题讨论】:

  • 是的,使用验证码或类似技术,每隔一段时间或每个请求都会更改一些东西,这都是愚蠢的,验证并检查服务器上发布的内容以及频率可能比只是重载你的浏览器来做一些无论如何都可以绕过的事情。

标签: java javascript jquery csrf


【解决方案1】:

使用较新版本的 jQuery:

$(document).on("submit", "form", function(e){ 
    e.preventDefault(); 
});  

使用较新版本的 jQuery,但允许在具有数据旁路的表单上提交表单:

$(document).on("submit", "form:not([data-bypass])", function(e){ 
    e.preventDefault(); 
}); 

参考:

http://addyosmani.github.io/backbone-fundamentals/

看看 Addy Osmani 如何处理劫持锚标签。

【讨论】:

    【解决方案2】:

    在您的简单想法中,您将事件绑定到document,但我会将实时侦听器绑定到"form" - 选择所有表单标签。另外,在事件监听器中,只需添加e.preventDefault()。像这样:

    $("form").live("submit", submitListener);
    
    function submitListener(e) {
       // your handling stuff goes here
       e.preventDefault();
    }
    

    我以前在我的表单上做过上述方法,它似乎工作正常。希望这能解决问题!

    编辑:我只是想确保这确实有效,so here's a quick example。如您所见,它阻止了对 google.com 的提交,并闪烁“不!”显示提交被阻止。

    【讨论】:

    • 这似乎确实有效......我做了这么多工作有点令人沮丧 - 发誓我试过这个($(document)和$(“form”))。好吧,无论如何,谢谢。
    • 只是想,这当然错过了 JS myForm.submit() 调用 :( 见jsfiddle.net/edslocombe/skSw8/16
    • 嘿 Ed,在这里查看最新版本,了解我将如何处理它:jsfiddle.net/skSw8/17
    【解决方案3】:

    我没有过多地弄乱 HTML 结构,而是创建了另一种方法。在页面卸载前设置cookie,并在服务器端检查cookie的存在和有效性。

    $(window).unload(function(){
        //30 seconds SHOULD be enough to connect to the server
        document.cookie = "crf=" + myTokenAddFn() + "; max-age=30";
    });
    

    【讨论】:

    • 也许这是我的答案...我希望避免非 JS 更改,因为 servlet 运行良好并且已经通过测试,但也许需要进行此更改。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多