实际上,cors和jsonp都是用于解决跨域问题,当两个页面的协议、域名、端口号中有一个不一致时就存在了跨域,一旦出现跨域,浏览器发送跨域请求后,请求回来的数据都会被浏览器所拦截,准备一张图给大家看看:
什么是JSONP
(???)
JSONP
(JSON with Padding
) 是 JSON
的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。
JSONP
的实现原理(???)?
-
概念:浏览器端通过 <script>
标签的 src
属性,请求服务器上的数据,同时,服务器返回一个函数的调用。这种请求数据的方式叫做 JSONP
-
特点:?
???JSONP
不属于真正的 Ajax
请求,因为它没有使用 XMLHttpRequest
这个对象
? ? JSONP
仅支持 GET
请求,不支持 POST
、PUT
、DELETE
等请求
什么是CORS(?????)
-
CORS
(跨域资源共享) 由一系列 HTTP
响应头组成,这些 HTTP
响应头决定浏览器 是否阻止前端 JS 代码跨域获取资源
-
浏览器的同源安全策略默认会阻止网页“跨域”获取资源。但如果接口服务器配置了 CORS 相关的 HTTP 响应头,就可以解除浏览器端的跨域访问限制
?
?
下面分别向大家演示通过CORS和JSONP实现跨域的案例:
一、通过CORS中间件解决跨域问题 :
index.html文件代码演示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="jquery.min.js"></script>
</head>
<body>
<button class="get">get请求</button>
<button class="post">post请求</button>
<script>
$('.get').on('click', function() {
$.ajax({
method: 'get',
url: 'http://127.0.0.1/api/get?name=hua&age=18',
success: function(res) {
console.log(res);
}
})
})
$('.post').on('click', function() {
$.ajax({
method: 'post',
url: 'http://127.0.0.1/api/post',
data: {
name: 'lajitong',
age: '111'
},
success: function(res) {
console.log(res);
}
})
})
</script>
</body>
</html>
此时会出现跨域问题,我们需要使用 cors 中间件解决跨域问题
-
cors 是 Express 的一个第三方中间件。通过安装和配置 cors 中间件,可以很方便地解决跨域问题
-
使用步骤
-
express接口案例代码
// 导入 express 模块
const express = require('express')
// 创建 express 的服务器实例
const app = express()
// 导入中间件
const cors = require('cors')
// 配置中间件
app.use(cors())
// 配置解析表单数据的中间件
app.use(express.urlencoded({ extended: false }))
// 导入路由模块(被单独分离后导入)
const router = require('./apiRouter')
// 把路由模块,注册到 app 上
app.use('/api', router)
// 调用 app.listen 方法,指定端口号并启动 web 服务器
app.listen(80, () => {
console.log('http://127.0.0.1')
})
apiRouter路由文件代码:
const express = require('express');
const router = express.Router();
router.get('/get', (req, res) => {
const query = req.query;
res.send({
status: 0,
msg: 'get请求成功',
data: query
})
})
router.post('/post', (req, res) => {
// const body = req.body; //获取客户端请求的数据
res.send({
status: 0,
msg: 'post请求成功',
data: req.body
})
})
module.exports = router;
在终端中运行express接口代码后打开index.html文件并点击get及post按钮得到请求结果:
?二、通过JSONP中间件解决跨域问题 :
创建 JSONP
接口的注意事项
-
如果项目中已经配置了 CORS
跨域资源共享,为了防止冲突,必须在配置 CORS
中间件之前声明 JSONP
的接口
否则 JSONP
接口会被处理成开启了 CORS
的接口
-
实现步骤:
? ? ? ? (1)获取客户端发送过来的回调函数的名字
????????(2)得到要通过 JSONP
形式发送给客户端的数据
????????(3)根据前两步得到的数据,拼接出一个函数调用的字符串
????????(4)把上一步拼接得到的字符串,响应给客户端的 <script>
标签进行解析执行
案例代码如下:
//导入express模块
const express = require('express');
//创建express服务器实例
const app = express();
//挂载路由
app.get('/jsonp', (req, res) => {
// 通过解构req.query客户端通过查询字符串的形式发送到客户端的参数fn
const { callback } = req.query
//在服务器端定义一个obj对象
const obj = {
uname: 'zjj',
age: '18'
}
//obj对象转为res.send可处理的字符串形式后从服务器端相应回调函数至客户端
res.send(`${callback}(${JSON.stringify(obj)})`)
})
app.listen(80, () => {
console.log('http://127.0.0.1');
})
创建jsonp.html客户端来接收服务器端响应过来的回调函数,代码如下:
url中callback=fn为客户端发送请求携带的参数 既服务器端中的req.query.callback
<script>
function fn(res) {
console.log(res);
}
</script>
<script src="http://127.0.0.1/jsonp?callback=fn"></script>