文章目录
- 1. 引言
- 2. 同源策略和跨域
- 3. html 存在的特殊情况
- 4. JSONP
- 5. JSONP优缺点
- 参考链接
1. 引言
在实际开发中,数据都是
后端
返回的,那就需要前端调用后端的接口
,来拿到数据
前端中调接口的方式一般有如下三种
- Ajax
- fecth
axios
这个是最常用的
涉及到调后端接口的话,后端的接口和前端肯定
不在一个端口
,甚至不在一个 域名下,这样就会导致跨域
fetch('https://editor.csdn.net/md?not_checkout=1&spm=1011.2415.3001.6217&articleId=141032145')
因为请求的主机地址 和 请求的地址, 协议端口域名都不一样,所以导致了
跨域
2. 同源策略和跨域
同源策略
同源:协议
、域名
、端口
,三者全部相同,才是同源。
同源策略是浏览器最核心也最基本的安全机制,它限制了来自不同源(即域、协议或端口)的文档或脚本之间的交互操作。
具体来说,同源策略要求如果两个页面的协议、域名和端口均相同,则它们被视为同源
,否则即为非同源。
根据同源策略,浏览器只允许当前网页与同一源下的其他资源进行交互,包括读取和修改。
换句话说,JavaScript脚本在一个源中加载的页面只能与同一源中的页面进行通信,而无法直接对不同源的页面进行读写操作。
同源策略的主要目的是防止恶意网站窃取或篡改其他网站的敏感信息,从而保护用户的隐私和安全。
跨域
协议、域名、端口,只要
有一个的不同
,就是跨域。
URL | 是否跨域 | 备注 |
---|---|---|
http://www.baidu.com/1.html 和 http://www.baidu.com/2.html | 否 | 协议端口域名一样,即为同源 |
http://www.baidu.com/1.html 和 http://www.csdn.com/2.html | 是 | 域名不同 |
http://www.baidu.com:7000/1.html 和 http://www.baidu.com:8000/2.html | 是 | 端口不同 |
https://www.baidu.com/1.html 和 http://www.baidu.com/2.html | 是 | 协议不同 |
注意: localhost 和 127.0.0.1 也是构成了
跨域
3. html 存在的特殊情况
html 中 有以下几个标签, 是可以引入与当前页面不同(
跨域
) 的地址的
- script标签
- img 标签
- link 标签
- video 标签
- audio 标签
- iframe 标签
4. JSONP
JSONP 其实是 跨域的一种解决方案 JSONP 全称“JSON with Padding”,译为“带回调的 JSON”,它是 JSON 的一种使用模式。通过 JSONP 可以绕过浏览器的同源策略,进行跨域请求。
jsonp 的本质是:利用 script 标签的
src 属性
不受跨域的影响 。
前端具体操作
- 在JS脚本中,先 定义一个
函数
用来处于后端返回的数据 - 通过js 脚本,创建
script
标签,src
设置为后端接口地址,并且请求地址中加上 第一步定义的函数名称
- 把这个
script
插入到DOM中,调用接口
后端具体操作
- 开启一个接口服务
- 解析出来请求地址查询参数中的
callback
的值 - 返回文本类型,格式是 callback的值(后端数据) 比如:abc([{name:”1"},{ name:“2” }])
服务器返回的内容,必须是一段可执行的 JavaScript 代码,不能是其它内容
前端代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button>点击调用接口</button>
<script>
function getUser(list) {
console.log('user', list);
// 创建一个新的空白的文档片段
let fragment = document.createDocumentFragment();
list.forEach(item => {
let div = document.createElement('div');
div.innerHTML = item.name;
fragment.appendChild(div);
});
document.body.appendChild(fragment);
}
document.querySelector('button').onclick = function () {
// 1、创建script 标签
let scriptEl = document.createElement('script');
// 2、设置 src 地址,并且传递过去 处理返回数据的函数名称
scriptEl.src = 'http://127.0.0.1:8080/api/getUserList?callback=getUser';
// 3、插入到DOM
document.body.appendChild(scriptEl);
}
</script>
</body>
</html>
后端代码如下
const htpp = require("http");
const url = require("url");
const querystring = require("querystring");
const userList = [
{ id: 1, name: "张三" },
{ id: 2, name: "李四" },
{ id: 3, name: "王五" },
];
const server = htpp
.createServer((req, res) => {
const parsedUrl = url.parse(req.url);
const queryParams = querystring.parse(parsedUrl.query);
console.log(req.url, queryParams);
if (req.url.split("?")[0] === "/api/getUserList") {
res.end(`${queryParams.callback}(${JSON.stringify(userList)})`);
} else {
res.end("404 Not Found");
}
})
.listen(8080);
5. JSONP优缺点
优点
- 相对简单:容易实现
- 兼容性好:由于JSONP依赖于
script标签
,它可以在老旧的浏览器中工作,不需要现代浏览器支持的高级功能或API。
缺点
- 只支持get 请求
- 安全性不好
可以使用其他的跨域方案,并不一定非得使用JSONP
参考链接
- createDocumentFragment MDN