同源:符合“协议+域名+端口”三者相同,就是同源。
同源策略:同源策略,初衷是为了浏览器的安全性,保证浏览器不易受到XSS、CSFR等攻击。
同源策略限制的内容有:
- Cookie、LocalStorage和IndexedDB等存储性内容
- DOM和JS对象
- AJAX请求发送后,被浏览器拦截
但是有三个标签是允许跨域加载资源:
- <img src=xxx>
- <link href=xxx>
- <script src=xxx>
JSONP和AJAX对比:
JSONP和AJAX相同,都是客户端想服务器端发送请求,从服务器端获取数据的方式。但AJAX属于同源策略,JSONP属于非同源策略(跨域请求)。
JSONP优缺点:
优点:简单兼容性好,可用于解决主流浏览器的跨域数据访问的问题。
缺点:仅支持get方法具有局限性,不安全可能会遭受XSS攻击。
解决方案:
- 通过jsonp跨域
- document.domain + iframe跨域
- location.hash + iframe
- window.name + iframe
- postMessage跨域
- 跨域资源共享(CORS)
- nginx反向代理跨域
- nodejs中间件代理跨域
- webSocket协议跨域
JSONP的原理:
其本质是利用了script标签具有可跨域的特性,在页面中插入一个script标签,创建一个callback回调函数,通过服务器配合执行callback回调函数,并传入一些参数,最后将这些数据返回到客户端。
客户端:
<script>
function fuc(data){
console.log(data.name);
}
</script>
<script src="http://www.baidu.com/api.php?callback=fuc"></script>
服务器端:
<?php
$cb = $_GET['callback'];
$data = array(
'name'=> 'zs',
'age'=>18,
'gender'=>true
);
echo $cb.'('.json_encode($data).')';
?>
JSONP封装:
function jsonp({ url, params, callback }) {
return new Promise((resolve, reject) ={
let script = document.createElement('script')
window[callback] = function(data) {
resolve(data)
document.body.removeChild(script)
}
params = { ...params, callback } // wd=b&callback=show
let arrs = []
for (let key in params) {
arrs.push(`${key}=${params[key]}`)
}
script.src = `${url}?${arrs.join('&')}`
document.body.appendChild(script)
})
}
jsonp({
url: 'http://localhost:3000/say',
params: { wd: 'Iloveyou' },
callback: 'show'
}).then(data ={
console.log(data)
})