源
源=协议+域名+端口(默认端口80)
window.origin或location.origin可以查询源
同源策略
浏览器规定,只有同源之间才能相互访问数据,即源的三者必须完全一致。注意,与子域名间非同源。否则浏览器会拦截。IE有特例:
- 授信范围(Trust Zones):两个相互之间高度互信的域名,如公司域名(corporate domains),则不受同源策略限制。
- 端口:IE 未将端口号纳入到同源策略的检查。
跨域
跨域就是不同源之间的操作,而浏览器会限制数据读操作(cross-origin-read),但允许跨域写操作(Cross-origin writes),如链接;允许跨域资源嵌入(cross-origin-empedding),如script标签、img标签等
跨域方法
CORS(CrossOriginResourceSharing)是HTTP的一部分。服务端设置响应头.方法一直接方便。但是IE9以下不支持
response.setHeader('Access-Control-Allow-Origin', 'http://deibo.com:9999')
JSONP.由于浏览器允许跨域资源嵌入,所以利用script标签。流程是请求方利用script标签请求数据方,数据方拿到查询参数中的函数名(callback),而后回调该函数把序列化的数据作为参数传入。
他的优点是:兼容IE,实现了跨域.缺点是:由于是script标签的引用所以不能发POST请求,而且拿不到状态码,响应头
请求方:
function jsonp(url) {
return new Promise((resolve, reject) => {
const random = Math.random()// 获得一个随机数的函数名
window[random] = (data) => {
resolve(data)
}
const script = document.createElement('script')
script.src = url + `?callback=${random}`// 查询参数中把函数名传过去,利用回调的方式获得数据,这里约定了functionName为callback
document.body.appendChild(script)
script.onload = () => {
script.remove()
}
script.onerror = () => {
reject()
}
})
}
jsonp('http://qq.com:8888/data.js')
.then((data) => { console.log(data); }, () => { console.log('失败了'); })
数据方:
if (path === '/data.js') {
if (request.headers.referer.indexOf('http://deibo.com:9999/') === 0) {// 检查请求头的referer
response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
response.statusCode = 200
const callback = query.callback// 找到请求路径的查询参数中的函数名
let data = fs.readFileSync('db/friends.json').toString()
let string = 'window["{{xxx}}"]({{data}})'
let string2 = string.replace('{{data}}', data)// 把js文件预留占位符替换成数据
let string3 = string2.replace('{{xxx}}', callback)// 把js文件的函数名换成请求穿过来的随机数函数名
response.write(string3)
} else {
response.statusCode = 404
}
response.end()
}