JSONP方式解决跨域
为什么会有JSONP
在WEB应用普及的今天,个人信息(账号、COOKIE等)广泛应用于网页。浏览器同源策略保证了WEB环境的安全性。同源策略是说,在a.com域名下通过ajax或者XmlHttpRequest等方式访问b.com的资源时,是不被允许的。
然而在很多时候,出于业务的的需要,我们经常有类似的跨域访问 的需求。浏览器有一些支持跨域访问的标签,例如script,img等。有这样的需求,自然就衍生了一些解决办法。
比较普遍的是通过jsonp的方式来实现接口--不建议使用这种方式.这里只是做一个总结学习
为了便于客户端使用数据,逐渐形成了一种非正式传输协议,人们把它称作JSONP,该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。
注意点:使用jsonp实现跨域需要服务端配合
代码实现
客户端
其对应的jsonp方式的用法如下,其中jsonpCallback是客户端实现的处理json数据的函数
前端页面在调用接口时,需要以callback=jsonpCallback的形式,将本地实现的处理json数据的函数上传到服务器。跨域服务器实现相应的jsonp接口,实际使用是要动态创建
<!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>
<script>
// 需要保存数据
var data = [];
// callback 参数
function jsonpCallback(res) {
console.log(res)
}
</script>
<script src="http://localhost:3000/web_list?callback=jsonpCallback"></script>
</body>
</html>
服务端
服务端使用express搭建,mysql连接数据库,服务端看你选用的语言,都是拼接字符串
const express = require('express');
const app = express();
const mysql = require('mysql');
const connection = mysql.createConnection({
host: '127.0.0.1',
user: 'root',
password: 'root',
database: 'node_mysql'
})
// 连接数据库
connection.connect();
app.get('/web_list', (req, res) => {
res.writeHead(200, { 'Content-type': 'text/html;charset=utf-8' })
connection.query('select * from websites', (err, result) => {
if (err) {
console.log('查询失败')
} else {
// 使用callback参数作为函数名来包裹住JSON数据
res.end(req.query.callback +'('+JSON.stringify(result)+')')
}
})
})
上面的代码应该可以看明白了吧,jsonp的方式无非就是通过给服务端传递一个参数(这个参数需要前后端协商,一般为callback),然后服务端处理数据返回的时候用客户端传递的参数值作为函数名包裹数据,这样前端在页面使用script标签请求时,数据就被带到函数名的默认参数了,这个时候就可以拿到数据
安全的问题
1、JSONP导致的劫持漏洞
2、JSONP导致的XSS漏洞
这里针对ajax与jsonp的异同再做一些补充说明:
1、ajax和jsonp这两种技术在调用方式上”看起来”很像,目的也一样,都是请求一个url,然后把服务器返回的数据进行处理,因此jquery和ext等框架都把jsonp作为ajax的一种形式进行了封装。
2、但ajax和jsonp其实本质上是不同的东西。ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加script标签