同源策略
在控制台输入 window.origin
源=协议+域名+端口
协议 +域名+端口号 完全一致 才是同源
浏览器不允许跨域
同源策略是限制的数据访问,我们并看不见里面的数据。
能引用这个js 但是不能读取里面的数据
举例(省略http协议)
假设frank.com/index.html引用了cdn.com/1.js
那么就说{1.js运行在源frank.com里 }
注意这跟cdn.com没有关系,虽然1.js从它那下载
所以1.js就只能获取frank.com的数据
不能获取1.frank.com或者qq.com的数据
目的
为了保护用户隐私
举个例子:
假设有一个kang.com 网站和qq.com网站文件夹状况如下
在没有使用跨域的状态下,如果kang.com 想使用 qq.com里面的friends.json 。是无法那到里面的相关数据。
会报如下错误
这里的请求是发成功了的,但是没有拿到数据
实现跨域
CORS
在server.js里面添加
response.setHeader("Access-Control-Allow-Origin", "允许的网址")
代码展示:
if(path === "/friends.json") {
response.statusCode = 200
// 允许跨域访问
response.setHeader("Access-Control-Allow-Origin", "http://kang.com:9999")
response.setHeader("Content-Type", "text/json;charset=utf-8")
response.write(fs.readFileSync("./public/friends.json"))
response.end()
}
jsonp
我们在跨域的时候由于当前浏览器不支持CORS,我们必须使用另一种方式来跨域
于是我们就请求一个js文件,js文件会执行一个回调,回调里面就有个数据。
回调里面的名字可以随机生成的,一个随机数,这个名字再以callback的参数传给后台
后台会吧函数再次返回给我们并执行。
优点:
- 兼容IE
- 可以跨域
缺点
- 由于它是script标签 不能像AJAX读取到状态码和请求头,只知道成功和失败,
- 由于它是script标签 只能发GET请求,不支持POST。
代码展示:
// 服务器里面的代码
if (path === "/friends.js") {
if (request.headers["referer"].indexOf("http://kang.com:9999") === 0) {
response.statusCode = 200
response.setHeader("Content-Type", "text/javascript;charset=utf-8")
const string = "window['{{xxx}}']({{data}})"
const data = fs.readFileSync("./public/friends.json").toString()
const string2 = string
.replace("{{data}}", data)
.replace("{{xxx}}", query.callback)
response.write(string2)
response.end()
} else {
request.statusCode = 404
response.end()
}
}
// jsonp 代码 封装后的
function jsonp(url) {
return new Promise((resolve, reject) => {
const random = "kangJSONPCallbackName" + Math.random()
window[random] = (data) => {
console.log(data)
}
// 创建script标签并引用链接
const script = document.createElement("script")
script.src = `${url}?callback=${random}`
// 加载完后就删除script标签
script.onload = () => {
script.remove()
}
script.onerror = () => {
reject()
}
// 将script插入body里面
document.body.appendChild(script)
})
}
// 输入可以跨域的地址
jsonp("http://qq.com:8888/friends.js").then((data) => {
console.log(data)
})
其他疑问
为什么a.qq.com访问qq.com也算跨域?
答:因为历史上,出现过不同公司共用域名,a.qq.com和qq.com不一定是同一个网站,浏览器谨慎起见,认为这是不同的源
为什么不同端口也算跨域?
答:原因同上,一个端口一个公司。记住安全链条的强度取决于最弱一环,任何安全相关的问题都要谨慎对待
为什么两个网站的IP是一样的,也算跨域?
答:原因同.上,IP可以共用。
为什么可以跨域使用CSS、JS和图片等?
答:同源策略限制的是数据访问,我们引用CSS、JS和图片的时候,其实并不知道其内容,我们只是在引用。