同源策略
- 同协议+同端口+同域名
JSONP解决方案
- 核心:通过动态添加
<script>
来调用服务器提供的js脚本 - 原理:为了减轻web服务器的负载,把js,css,img等静态资源分离到另一台独立域名服务器上,在html页中通过相应的标签从不同域名下加载静态资源
- 限制:JSONP只能发GET请求,因为本质上script加载资源就是GET
- 过程
- 本地服务器声明一个回调函数,其函数作为参数值,传递给跨域请求的服务器,
callback=function_name
- 创建一个script标签,把跨域的接口地址赋值给src,在这个地址中传递callback
- 服务器接受请求,对数据进行拼接处理
- 服务器通过http协议把数据返回给服务端,服务端再调用自己的回调函数
- 本地服务器声明一个回调函数,其函数作为参数值,传递给跨域请求的服务器,
- 原生实现
<script>
var sc=document.createElement('script');
sc.type='text/javascript';
sr.src='http://www.balabla.com:8080/login?user=huihui&callback=solve';
document.head.appendChild(script);
//回调函数
function solve(res){
alert(JSON.stringify(res));
}
</script>
- jquery ajax
$.ajax({
url:'http://www.balabla.com:8080/login',
type:'get',
dataType:'jsonp',//请求方式为jsonp
jsonpCallback:'solve',
data:{]
});
- vue.js
this.$http.jsonp('http://www.balabla.com:8080/login',{
params:{},
jsonp:'solve'
}).then((res)=>{
console.log(res);
})
document.domain+iframe跨域
适用于唯一主域相同,子域不同的跨域应用场景
- 原理:两个页面都是js强制设置document.domain为基础主域,就实现了同域
父窗口(http://www.domain.com/b.html)
<iframe id="iframe" src="http://child.domain.com/b.html"></iframe>
<script>
document.domain="domian.com";
var user="admin";
</script>
子窗口 (http://child.domain.com/b.html)
<script>
document.domain='domain.com';
alert('get js data from parent-->'+window.parent.user);
</script>
location.hash+iframe跨域
三个页面,不同域之间利用iframe的location.hash传值,相同域之间直接js访问来通信
CORS跨域资源共享
在使用cors时,http请求会被划分为两类,简单请求和复杂请求,这两种请求的区别在于是否会触发cors预检请求
CORS允许浏览器向跨源服务器发出XMLHTTPRequest请求,从而克服了AJAX只能同源使用的限制。
cors原理
- 跨域资源共享cors标准新增了一组HTTP首部字段,允许服务器声明哪写源站可以通过浏览器有权访问哪写资源。
- 对那些可能会对服务器数据产生副作用的HTTP请求方法(GET之外的HTTP或者搭配某些MIME的POST请求),浏览器必须用OPTIONS方法发起一个预检请求(preflight request),从而货之服务端是否允许该跨域请求,服务器确认允许之后才发起实际的HTTP请求。
- 在预检请求的返回中,服务器端也可以通知客户端,是否需要携带身份凭证(Cookies和HTTP人正相关数据)
- cors通信的关键是服务器,只要服务器实现了CORS接口,就可以跨源通信
简单请求与复杂请求
- 使用方法之一:GET、POST、HEAD
- 不得人为设置该集合之外的其他首部字段:Accept,Accept-Launguage,Content-Language,Content-Type
- Content-Type的值不能是下列三者之一:text/plain,multipart/form-data,application/x-www-form-urlencoded
- XMLHttpRequestUpload对象没有注册过任何时间监听器;可以使用XMLHttpRequest.upload属性访问
- 请求中没有使用ReadableStream对象
除了简单请求外都是复杂请求
- 如果是简单请求——只需要在服务器响应头中加
Access-Control-Allow-Origin
,表明跨源服务器 - 如果是复杂请求——需要发送预检请求options
请求过程
- Browser给Server发送预检请求preflight request
- server会给browserpreflight response
- browser发给server 正式请求 real request
- server发给browser回应real response
preflight request
Accept:
Accept-Encoding:gzip,deflate,sdch
Accept-Language:zh-CN,zh;q=0.8
Access-Control-Request-Headers:access-control-allow-origin
Access-COntrol-Request-Method:GET
Connection:keep-alive
Host:localhost:8888
Origin:http://localhost:63342
preflight response
Access-Control-Allow-Origin:http://localhost:63342 //允许跨域资源
Access-Control-Max-Age:3600
Access-Control-Allow-Methods;GET,POST,DELETE,PUT
Access-Control-Allow-Headers:access-control-allow-origin
Access-Control-Allow-Credentials:true//使用cookie