- JSONP: 利用script标签立即下载并执行的特性,就可以在回调函数中拿到返回来的数据。
// 1.回调函数
function handleResponse(data){
console.log(data);
}
// 2.动态创建 script
var script = document.createElement('script');
script.src = 'http://test.com/json?callback=handleResponse';
document.body.insertBefore(script,document.body.firstChild);
缺点:
- 仅限于GET请求
- 有安全问题,万一有恶意代码返回,前端无法阻止
- 无法检测请求是否成功
- CORS: CORS是跨域资源共享(Cross-origin resource sharing), 利用这个技术关键是在于服务端,设置返回的Access-Control-Allow-Origin响应头允许跨域操作。
发送请求时有两种情况:
- 简单请求
方法: GET、HEAD、POST
Content-Type的值:text/plain、multipart/form-data、application/x-www-form-urlencoded发起简单请求,浏览器判断是简单请求的话就会在请求头添加origin字段,值是发起请求的所在的源。服务端收到请求后会判断origin是否在自己的许可范围,如果不在就拒绝,如果在就会有以下的响应头添加:
- Access-Control-Allow-Origin(必选):告诉客户端我接受请求,值为origin的值,若允许所有源请求就会返回 *。
- Access-Control-Allow-Credentials(可选):告诉浏览器发送请求时携带Cookie,true表示允许false表示禁止。
- Access-Control-Expose-Headers(可选):额外给客户端返回的头部字段。
- 复杂请求
复杂请求会有两次,第一次是发送一个预检请求,使用的方法是options,询问服务器是否允许我进行跨域请求资源。并且允许客户端自定义请求头的类型,询问服务器是否允许。
Origin: http://test.com Access-Control-Request-Method: PUT Access-Control-Request-Headers: Custom-Header1,Custom-Header2 Host: target.com Accept-Language: en-US Connection: keep-alive User-Agent: Mozilla/5.0...
然后服务器会进行验证,还会在响应头进行说明允许你的请求。
HTTP/1.1 200 OK Date: Mon, 01 Dec 2008 01:15:39 GMT Server: Apache/2.0.61(Unix) Access-Control-Allow-Origin: http://test.com Access-Control-Allow-Methods: GET, POST, PUT Access-Control-Allow-Headers: Custom-Header1,Custom-Header2 Access-Control-Max-Age: 1728000 Content-type: text/html; charset=utf-8 Content-Encoding: gzip Content-Length: 0 Keep-Alive: timeout=2, max=100 Connection: Keep-Alive Content-Type: text/plain
- Access-Control-Allow-Origin:告诉客户端,允许你这个源的请求
- Access-Control-Allow-Methods:告诉客户端,服务端允许的跨域 AJAX 请求的类型,也可进行 GET 或者 POST 请求
- Access-Control-Allow-Headers:告诉客户端,服务端允许的发送请求时的自定义请求头
- Access-Control-Max-Age: 告诉客户端预检请求的有效期,省去了多次的预检请求。也就是说,1728000 秒内你可以直接发送真正的 AJAX 请求,不用每次询问
- Nginx代理: 将nginx目录下的nginx.conf修改,通过反向代理的方式来实现跨域请求。
# /所有以apis开头发起的请求会被分发到myserver
location ^~ /apis/ {
proxy_pass http://myserver; # 负载均衡名,写你请求的服务器地址
proxy_set_header X-real-ip $remote_addr;
proxy_set_header Host $http_host;
}
-
document.domain: 该方式只能用于二级域名相同的情况下,比如 a.test.com 和 b.test.com 适用于该方式,只需要给页面添加 document.domain = ‘test.com’ 表示二级域名都相同就可以实现跨域。
-
window.name: 页面如果设置了window.name,那么在不关闭页面的情况下,即使进行了页面跳转location.href=…,这个window.name还是会保留。
// 打开必应 https://www.bing.com/
// 打开控制台
> window.name
""
> window.name='test';
"test"
> location.href='http://www.google.com';
"http://www.google.com"
Navigated to https://www.google.com/
> window.name
"test"
- postMessage+iframe: 这种方式通常用于获取嵌入页面中的第三方页面数据。一个页面发送消息,另一个页面判断来源并接收消息。
postMessage(data,origin)方法接受两个参数:
- data:要传递的数据,html5规范中提到该参数可以是JavaScript的任意基本类型或可复制的对象,然而并不是所有浏览器都做到了这点儿,部分浏览器只能处理字符串参数,所以我们在传递参数的时候需要使用JSON.stringify()方法对对象参数序列化。
- origin:字符串参数,指明目标窗口的源,协议+主机+端口号[+URL],URL会被忽略,所以可以不写,这个参数是为了安全考虑,postMessage()方法只会将message传递给指定窗口,当然如果愿意也可以把参数设置为”*”,这样可以传递给任意窗口,如果要指定和当前窗口同源的话设置为”/“。
03 小结
// 发送消息端
<div>
<div id="color">Frame Color</div>
</div>
<div>
<iframe id="child" src="http://b.com/b.html"></iframe>
</div>
window.onload=function(){
window.frames[0].postMessage('getcolor','http://b.com');
}
// 接收消息端
window.addEventListener('message',function(e){
console.log(e)
},false);
备注: 参考http://blog.alanwu.website/2020/03/06/crossOrigin/
如果此文对你有用请动动你的小手点个赞!谢谢!!!
网友评论