-
Q1:为什么会产生跨域问题?
-
A1:浏览器具有两种同源策略,当你的操作违背了浏览器的同源策略自然就出现了(也就是出现了非同源的问题浏览器不能支持)
- 浏览器的同源策略
- 1.DOM同源策略:禁止对不同源的页面进行DOM操作
- 2.请求(ajax)的同源策略:
- 不同于其他资料的描述,我认为浏览器并没有阻止发送跨域请求,你发送的跨域请求仍然可以被服务器处理,但是请求处理完毕之后返回响应,这时候浏览器会去查看响应体的头部是否包含
Access-Control-Allow-*
。- 包含:服务器在响应发回来的时候在响应的头部加上了
Access-Control-Allow-*
- 1.服务器能够处理来自不同源的请求
- 2.浏览器检查了响应体的头部包含这些字段,则将响应体load返回给ajax请求的地方
- 不包含:服务器在响应发回来的时候没在响应的头部加上
Access-Control-Allow-*
- 1.服务器不能处理来自不同源的请求
- 2.浏览器检查了响应体的头部不包含这些字段,则不会load响应体,然后报出
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:1337' is therefore not allowed access. The response had HTTP status code 403.
- 包含:服务器在响应发回来的时候在响应的头部加上了
- 不同于其他资料的描述,我认为浏览器并没有阻止发送跨域请求,你发送的跨域请求仍然可以被服务器处理,但是请求处理完毕之后返回响应,这时候浏览器会去查看响应体的头部是否包含
- 3.浏览器默认阻止跨域请求发送cookie(不知道这算不算)
- 浏览器的同源策略
-
Q2:同源策略能帮助我们做什么呢?
-
A2:针对ajax同源
- 如果你登录银行网站a之后,请求回了有效cookie
- 然后登陆恶意网站B
- 由于每次请求都会在请求的头部带上cookie
- 所以恶意网站当你浏览的时候欺骗你点击一个button
- 然后使用带有银行cookie的请求头伪装成你,向银行系统发送请求
- 如果浏览器没有跨域限制
- 那么A网站就可以完全的处理来自B网站发送的请求并且认为是你发的请求,不仅仅会处理恶意网站的请求,还兴许会给恶意网站返回你的信息
- 如果浏览器有跨域限制
- 请求发送可能成功
- 但是至少不会拿到请求返回的内容
-
Q3:如果浏览器的同源策略不会阻挡跨域请求的发送,只会阻挡响应的load,那么恶意网站发送的是一个操作性的请求,比如一个post请求请求转账,或者是一个delete请求直接删除一个用户怎么办?
-
A3:W3c标准中要求:对那些可能对服务器数据产生副作用的 HTTP 请求方法(特别是 GET 以外的 HTTP 请求,或者搭配某些 MIME 类型的 POST 请求)
- 浏览器必须首先使用 OPTIONS 方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求。
- 服务器确认允许之后,才发起实际的 HTTP 请求。
-
Q4:那么浏览器怎么知道服务器是否能够处理跨域请求呢?
-
A4:
-
当你发送一个请求被浏览器检测除了是跨域的请求
-
浏览器会在请求的头部给你带上origin字段并且将你的协议域名和端口号一起发送给服务器
-
服务器接受请求会check是否能够处理来自这个域的请求
- 如果可以:则在响应头部带上
Access-Control-Allow-XXX
那三个字段,并将payload返回 - 如果不可以:则不在响应头带上那三个字段
- 如果可以:则在响应头部带上
-
当响应返回,浏览器check是否在响应中包含三个字段,再决定是否将payload继续发给请求者
-
Q5:但是对于跨域请求浏览器不是默认不在请求头中带上cookie或者authorization这些字段吗?如果服务器想check怎么办呢?
-
A5:想带上这些字段,浏览器比必须要求双方认可
- 发送请求的时候开启xhr.withCredentials = true;(不同的请求发送方式有不同的开启方式比如axios,可以直接设置withCredentials: true)
- 并且服务器也要在响应头返回
Access-Control-Allow-Credentials:true
-
Q6:为了避免跨域问题,我可以使用
<a href>
、<img src>``window.open
发送跨域get请求,也可以使用<form action>发送跨域的post请求,这为什么就可以做到?难道没有安全问题吗? -
A6:对于a和submit而言都是一旦发送请求就已经跳转到新的页面了,也就是新的页面接受请求的返回值,也不再是恶意网站接受了,所以浏览器认为这是安全的.
-
Q7:如何解决通过浏览器无法发送跨域请求的问题?
-
A7:
-
通过使用浏览器的标签避免跨域问题
- 可以使用window.open发送一个get请求
- 使用form表单发送post请求
-
使用CORS(跨域资源共享)的标准解决跨域问题
- 需要客户端(发送跨域请求,偶尔需要设置withCreditical为true)
- 需要浏览器(将origin字段加在请求头部中)
- 需要服务器将
Access-Allow-XXX
加在响应头部 - ---------->必须三者配合才能够完成一次跨域请求
-
-
Q8:浏览器不能处理跨域请求,那为什么使用postman,也就是不通过浏览器发送的http请求都没有安全防范呢?
-
A8:有人给出说法说,浏览器是公共的但是api是自家的也是不能够说服我的,这个需要再找资料学习学习~
网友评论