为什么 Content-Type 是 'text/plain' 或
'应用程序/json'?
三个content types (enctype) supported by a form如下:
application/x-www-form-urlencoded
multipart/form-data
text/plain
如果 Web 服务器上的处理程序接收到表单,并且它不是上述内容类型之一,则可以假定它是发送表单的 AJAX 请求,而不是 HTML <form /> 标记.
因此,如果现有的 pre-CORS 系统为了防止Cross-Site Request Forgery (CSRF) 使用内容类型作为确保请求不是跨站点的方法,那么 CORS 规范的作者不想引入现有网站的任何新安全漏洞。他们通过坚持此类请求启动预检来确保浏览器和服务器首先兼容 CORS 来做到这一点。
它不关心 POST 是否破坏了数据库,它只关心那个
浏览器无法读取该操作的输出
完全正确。默认情况下,浏览器遵循Same Origin Policy。 CORS 放宽了这个限制,允许另一个 Origin 读取 AJAX 的响应。
为什么会有飞行前请求?
如前所述,确保客户端和服务器都兼容 CORS,而不仅仅是发送的 HTML 表单始终能够跨域提交。
例如这一直有效。 example.com POSTing 到 example.org 的表单:
<form method="post" action="//example.org/handler.php" />
仅此还不够
检查类似“Access-Control-Allow-Cross-Origin-Request:”的标头
回复中的“真实”?
因为 CSRF 向量。通过检查浏览器是否可以发送预检,它确保跨域请求在浏览器发送之前被授权(通过检查 CORS 响应标头)。这使浏览器能够保护当前用户的会话 - 请记住,这里的攻击者不是运行浏览器的人,受害者在 CSRF 攻击中运行浏览器,因此被操纵的浏览器无法正确检查 CORS 标头或欺骗预检对攻击者自己运行没有任何好处。同样,预检使 custom headers 等 CSRF 缓解措施发挥作用。
总结:
HTML 表单跨域
- 只能与某些
enctype's 一起发送
- 不能有自定义标题
- 浏览器将直接发送它而无需预检,因为关于
<form> 提交的所有内容都是标准的(或 CORS 所说的 "simple")
- 如果服务器处理程序收到来自此类表单的请求,它将对其进行处理
AJAX 跨域
- 只能通过 CORS 实现
- 某些浏览器的早期版本,例如IE 8 & 9 可以发送跨域请求,但不能使用非标准标头或
enctype's
- 在fully supported browsers 中可以有自定义标题和
enctype
- 为了确保跨域AJAX请求不会欺骗同源AJAX请求(记住过去不可能跨域),如果AJAX请求不是simple那么浏览器将发送预检以确保允许这样做
- 如果服务器处理程序收到一个请求,它将对其采取行动,但前提是它已通过预检检查,因为初始请求将使用 OPTIONS 动词发出,直到浏览器同意服务器正在谈论 CORS 是否会发送实际的 GET 或 POST