同源策略
同源策略(Same-Origin-Policy) 最早是由 Netscape 公司提出,是浏览器的一种安全策略。
即 不同源的页面之间,不准互相访问数据
- window.origin 或 location.origin 可以得到当前源。
- 同源:协议,域名,端口号,必须完全相同。
- 违背同源策略就是跨域
- ajax默认是遵循同源策略的。
举个栗子:
- qq.com 、 wwww.baidu.com 不同源
- baidu.com 、 www.baidu.com 不同源
- 协议,域名,端口号,必须完全相同才叫同源
CORS 实现跨域
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。
它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
但是IE10以下是不支持的。
如何使用
因为CORS与AJAX没有什么差别,只不过浏览器发现是AJAX请求跨源,就会在请求中自动添加一些附加的头信息。因此我们只需要以此判断是否可以跨域,在响应头中加入一些信息即可。
所以,CORS跨域的关键是在服务器,只要服务器实现了CORS接口,即可跨源通信。
简单请求:
response.setHeader('Access-Control-Allow-Origin', 'http://wangpf.com:9990')
注意:它的值要么是请求时Origin字段的值(协议 + 域名 + 端口),要么是一个*,表示接受任意域名的请求。
AJAX 和服务器代码展示:
http://wangpf.com:9990中的js内容:
const req = new XMLHttpRequest()
req.open('GET', 'http://qq.com:8888/friends.json')
req.send()
req.onreadystatechange = () => {
if (req.readyState === 4) {
if (req.status >= 200 && req.status < 300) {
console.log(req.response);
}
}
}
http://qq.com:8888 中服务端内容
if(path === 'friends.json'){
response.statusCode = 200
response.setHeader('Content-Type', 'text/json;charset=utf-8')
// console.log(request.headers['referer']);
response.setHeader('Access-Control-Allow-Origin', 'http://wangpf.com:9990')
response.write(fs.readFileSync('./public/friends.json'))
response.end()
}
JSONP 实现跨域
什么是JSONP?
JSONP(JSONP with Padding) 是一大堆牛逼的程序员想出来的跨域方法。
当前网站创造一个script标签去请求另一个网站的JS,然后这个JS文件会夹带一些数据,这些数据会在我的网站上调用全局函数运行。
JSONP是怎么实现的?
因为我们当前浏览器或者某些条件不支持CORS来实现跨域,所以我们必须要使用另外一种方式来跨域,于是我们就请求JS文件,这个JS文件会执行一个回调,这个回调里面就有我们的数据。
这个回调名字是可以随机生成的,我们把这个随机数以callback为参数传给后台,后台会把这个函数再次返回给我们并执行
JSONP的优点和缺点
优点:
- 支持IE
- 可以跨域(好像是废话哦。。。)
缺点:
- 由于它是script标签,它不能像AJAX一样,读出(拿到)状态码和响应头,它只知道成功和失败(用onload和onerror来监听)。
- 由于它是script标签,它只能发get请求,不支持POST。 JSONP的原理
- 网页有一些标签天生具有跨域的能力,比如:img link iframe script
- JSONP 就是利用 script标签的跨域能力来发送请求的(这也是jsonp跨域只能用get请求的原因所在)
封装一个JSONP函数
//封装JSONP函数 使用JSONP 实现
function JSONP(url) {
return new Promise((resolve, reject) => {
const random = 'WangpfCallbackName' + Math.random()
window[random] = (data) => {
resolve(data)
}
const script = document.createElement('script')
script.src = `${url}?callback=${random}`
document.body.appendChild(script)
script.onload = () => {
script.remove()
}
script.onerror = () => {
reject()
}
})
}
JSONP('http://qq.com:8888/friends.js')
.then((data) => {
console.log(data);
})