面试时被问到跨域问题,虽然答错了,但下来之后仔细研究,解决了一直以来的一个误区,跨域只是阻止数据的获取,请求并未拦截,也算小有收获
跨域
同源策略
同源策略是浏览器的一种安全策略,同源:协议、域名、端口号必须完全相同,违背同源策略是跨域
浏览器判断请求是否跨域
浏览器根据同源策略判断一个请求是否跨域
- 非跨域请求,请求头中只包含请求的主机名
- 跨域请求,在请求头中既包含要请求的主机名,还包含当前的源主机名,二者不一致,即是跨域请求
判断流程
浏览器对请求的分类
- HTTP 1.0: GET、POST、HEAD
- HTTP 1.1: GET、POST、HEAD、[OPTIONS、PUT、PATCH、DELETE、TRACE、CONNECT][新增]
浏览器根据请求方法和类型将请求划分为简单请求和非简单请求
简单请求:浏览器先发送请求再判断是否跨域
- 请求方法为GET、POST、HEAD
- 请求头header中无自定义的请求头信息
- 请求类型content-type为text/plain,multipart/form-data,application/x-www-form-urlencoded的请求
非简单请求:浏览器先发送预检命令(OPTIONS方法),检查通过后再发送真正的数据请求。
- 请求方法为PUT、DELETE的Ajax请求
- 发送JSON格式的Ajax请求
- 带自定义头的Ajax请求
预检命令会发送自定义头为
Access-Control-Request-Header:content-type
的请求到服务器,根据响应头中的
Access-Control-Allow-Headers:content-type
判断服务器是否允许跨域访问。预检命令跨可以进行缓存,服务器端设置
Access-Control-Max-Age:3600
这样后面发送相同跨域请求时就不用再发送预检命令了。
解决跨域
JSONP
JSONP(JSON with Padding),是一个非官方的跨域解决方案,纯粹凭借程序员的聪明才智开发,只支持get请求
-
工作方式:JSONP利用scrip标签的跨域能力来发送请求
-
使用步骤:
-
动态创建一个script标签
var script = doucument.createElement('script');
-
设置script的src,设置回调函数;
-
将script标签插入到文档中
document.body.appenChild(script)
-
CORS(跨域资源共享)
CORS是官方的跨域解决方案,特点是不需要在客户端做任何特殊的操作,完全在服务器中进行处理。支持get和post请求,跨域资源共享标准新增了一组HTTP首部字段,允许服务器声明哪些源站通过浏览器有权限访问哪些资源
- 工作方式:CORS是通过设置一个响应头来告诉浏览器,该请求允许跨域,浏览器收到该响应以后就会对响应放行
- 使用:对服务器端的设置:router.get(‘xxx’,function(req,res){})
代理服务器
浏览器存在同源策略,服务器之间不受同源策略限制。通过代理服务器实现跨域