为什么form表单提交没有跨域问题,但ajax提交有跨域问题?

貌似浏览器也不允许js修改已经存在的header,只能增加自定义header: ajax - Set a request header in JavaScript


因为原页面用 form 提交到另一个域名之后,原页面的脚本无法获取新页面中的内容。

所以浏览器认为这是安全的。

而 AJAX 是可以读取响应内容的,因此浏览器不能允许你这样做。

如果你细心的话你会发现,其实请求已经发送出去了,你只是拿不到响应而已。

所以浏览器这个策略的本质是,一个域名的 JS ,在未经允许的情况下,不得读取另一个域名的内容。但浏览器并不阻止你向另一个域名发送请求。


(原答案有问题,以下为修改的答案)

form 提交之后会更新页面,而假如更新到指定 iframe/window 中,如果是跨域的,父页面访问其内容一样受到 same origin 策略限制。


这样说不知道对不对,请大神指教。

跨域是浏览器行为,不是ecma的(这个不确定)。而且具体行为是,你的请求可以发送,浏览器也能收到正常的响应,只是返回给你的时候,浏览器检查了是不是跨域,是对话就阻止了。

所以form表单的发送请求是没有影响的。


首先多嘴一句跨域的唯一标准,就是你能不能通过类似请求(eg:$.get)的方式拿到别人的内容。

  1. form一般都是给别人请求,而不是别人的数据。
  2. form一般发完后,不需要别人反馈。或者说别人反馈了你也拿不到。 而ajax是一直在等别人的done or faill信息。 这就设计到上面别人信息了


所谓的跨域问题只是浏览器强加给js的规则而已,世界本无跨域限制。是浏览器强制不允许js访问别的域,但是浏览器却没有限制它自己。比如说img标签可以加载任何域的图片,script可以加载任何域的js。再比如说你不能从前端js去调淘宝的接口获取ip对应的城市地址信息,,但是你可以手敲在浏览器地址栏,直接打开。


ajax跨域是因为浏览器需要保护用户的安全和隐私而给js设定的限制。如果你自己写个浏览器去掉这个限制那js就可以任意跨域访问了

form表单可以跨域一个是历史原因要保持兼容性,一个是form表单会刷新页面不会把结果返回给js,所以相对安全

用jsonp跨域其实也是利用了浏览器的历史兼容性,而最新的font资源就不允许直接跨域引用


用安全术语来说就是为了保障数据的机密性。

传统表单提交(不设置target),只能提交到当前地址栏的URL,这个过程会伴随着非常明显的交互反馈,比如浏览器会刷新整个页面,如果有任何危险的操作势必会引起用户的警觉。

AJAX服务端响应过后,是脚本接管了整个后续过程,如果把form表单的target设置为iframe,那么也是那个iframe接管了后续所有操作,这些行为都是可以不发生任何交互上的反馈,也就是说用户根本无法觉察数据发生了泄漏,换句话说控制权其实交给了脚本,而不是与用户直接发生交互的浏览器,那么脚本对于用户来说是不可知不可信的,鬼知道这段脚本是业务逻辑还是攻击代码。

跨域问题只是同源策略中其中的一个安全策略,同源策略还包括协议,二级域名等。如果在允许https站点向同域名发起http的AJAX的请求,同样攻击者可以通过抓包获取敏感数据;也可以对二级域名进行DNS污染,把数据提交到攻击者的服务器上,造成数据泄漏。

所以多从攻击者角度去思考为什么会有这些限制。


因为浏览器安全策略限制的是脚本,而并不限制src,form提交之类的请求。

另外ajax是提交了的(调试工具中很容易看到请求已经发出),只是脚本无法获得结果。


你有这个疑问,可能原因还是在于没有理解为什么会有跨域。

跨域是浏览器的一种安全机制,form提交没有跨域是因为form提交情况下,跨域没有任何安全问题。ajax提交跨域,或者说iframe之间跨域,都会有安全问题。

具体的安全问题,之前写过一篇文章,你可以看一下 跨域的那些事儿 ,里面说了如果放开跨域可能产生的问题。同理,这些问题在form提交是不存在的。

其他答主回答的也很好,关键在于如果能得到服务器返回的信息,跨域是危险的。


传统form表单提交浏览器会发生跳转,这种并不能叫跨域啊!那我还想问为什么a标签跳转到别的域名不存在跨域呢?


Form表单的提交会刷新整个页面,对于移动端来说,会消耗很多流量

Ajax存在同源策略,只要域名、协议、端口号任何一个不相同都无法接收跨域的响应

同源策略的出发点是好的,可以保证用户信息的安全性问题,防止信息被窃取等

Ajax之所以可以实现跨域,主要是因为使用如JSONP方式动态生成script标签,然后将数据塞到函数内,或者使用CORS方式实现跨域

两种方法简单的说是避开了同源策略的限制


跨域限制的是从js里发起的请求,表单发起的请求并不需要js。


这应该跟是否刷新页面无关,据我观察,是否刷新页面也是请求完成之后的动作。根本原因应该是传统的表单提交不是从脚本发起的请求,所以无需遵循同源策略。

实验:我用ajax和传统的表单提交方式跨域请求 post http://baidu.com.

结果:ajax请求失败提示cors错误,表单提交后跳转到 百度页面 。

分析:其实两次请求的response其实是一样的,status code都是302。但是因为ajax从脚本发起的请求,所以受到了限制,缺少"access-control-allow-origin"的时候被当成错误的处理了。而表单提交不是从脚本发起的请求,所以不受影响,正常重定向到 百度。

原理:我也不知道,因为以上都是我编的,实在编不下去了了。随手甩下一段MDN的文档,顺便说一下,所谓的跨域限制,是浏览器拦截了响应而已,其实请求是成功的。

HTTP访问控制(CORS) 原文:

出于安全考虑,浏览器会限制从脚本内发起的跨域HTTP请求。例如,XMLHttpRequest 和 Fetch 遵循同源策略。因此,使用 XMLHttpRequest或 Fetch 的Web应用程序只能将HTTP请求发送到其自己的域。为了改进Web应用程序,开发人员要求浏览器厂商允许跨域请求。

(译者注:这段描述跨域不准确,跨域并非不一定是浏览器限制了发起跨站请求,而也可能是跨站请求可以正常发起,但是返回结果被浏览器拦截了。最好的例子是 CSRF 跨站攻击原理,请求是发送到了后端服务器无论是否跨域!注意:有些浏览器不允许从 HTTPS 的域跨域访问 HTTP,比如 Chrome 和 Firefox,这些浏览器在请求还未发出的时候就会拦截请求,这是一个特例。


表单是死的,js是活的,禁止表单目的何在?

js跨域就可以对目标网站为所欲为,而表单能做什么?他只是提交数据和请求而已。

建议问这个问题前先了解下get和post,以及js的区别。

表单无论是get还是post提交数据和目标网页反馈的数据都是反馈给当前浏览器,浏览器即是客户,况且返回到无论是什么都还是在目标域内。而js提交则是直接反馈给js,这就存在漏洞的可能,js严格意义讲,他不是客户是程序。

最简单的例子,黑客做一个一模一样的银行网页iframe真正的银行网页,跨域提交客户录入的账号和密码,而反馈的信息确是反馈给黑客而不是客户,导致客户信息泄漏。

现在很多web框架已经默认禁止跨域提交请求,例如php的laravel,就算你是表单跨域也是无法请求的。

所以本质不是表单和js的问题,而是get和post跨域的安全问题。


ajax是通过xmlhttp那个对象属性url来访问,这个会被浏览器发现跨域的。


不允许js跨域只是服务器的默认设置,以php为例,只要在响应php前面加上header("Access-Control-Allow-Origin: *");那就可以响应跨域的请求了。


个人以为可以这么想,为什么别人给你的银行账户转账的时候不需要密码,但是从你的帐号里面取钱的时候需要密码呢。


form的控制权在浏览器手里,ajax在你的手里。


我还以为在问跨域伪造呢


form把东西提交之后并不需要返回,而ajax需要


仔细看你会发现,其实ajax是可以发出去的,只是拿不到响应数据,可以打开preview看下。

而form表单提交后会跳到相应页面


我觉得传统的Form表单提交以后会跳转到一个新页面,如果用Java Spring写的话就是会返回一个model,浏览器重新渲染,此时前端是无法控制这个行为的,所以搞啥都可以?

至于Ajax,因为有响应,所以前端这边可以补抓到?不过在SPA浪潮下,我写过的Form表单基本都是用Ajax发出去的。

嗯感觉提了一个好问题,学习到了。


浏览器为了保证用户的安全与隐私。

浏览器的限制不是为了限制用户,而是为了限制代码的运行,毕竟代码是服务器提供的。

如果不限制代码的运行,万一用户不小心点击了恶意网站,那么用户的数据将不再安全。


推薦閱讀:

用於驗證的 Passport.js 與 JsonWebToken 是什麼關係?
「遵循XXX開源協議」這句話規定了什麼,我要把某個js工具用在項目中,我具體要做哪些事情才算遵循協議?
什麼是JS跨域訪問?
請問如果一個線程能夠非同步執行,是否是因為另一個線程幫其承擔了同步的操作?
理解 React,但不理解 Redux,該如何通俗易懂的理解 Redux?

TAG:Web开发 | 前端开发 | JavaScript | Ajax | 跨域 |