Open YvetteLau opened 5 years ago
JSONP(JSON with Padding)是数据格式JSON的一种“使用模式”,可以让网页从别的网域要数据。另一个解决这个问题的新方法是跨来源资源共享。
由于同源策略,一般来说位于server1.example.com的网页无法与 server2.example.com的服务器沟通,而HTML的
JSONP是解决跨域问题的一种方案,原理如下: 1、利用script标签的src属性实现跨域; 2、然后前端将回调函数作为参数传给服务器,服务器注入参数后再返回。
function jsonp(params) {
var script = document.createElement('script');
var url = params.url + '?callback=' + params.callback,;
script.src = url;
document.body.appendChild(script);
}
function fn (data) {
console.log(data)
}
jsonp({
url: 'your.url',
callback: fn
})
jsonp定义
JSONP是受限于浏览器的同源策略的一种跨域问题解决方案
原理
利用script标签的src属性 可以不受同源策略的影响,前端需定义一个回调函数,回调函数 作为参数在请求路径中拼接 ,会将请求得到的结果传入回调之中 前端拿到结果 做相应处理
实现
function jsonp(params){
var script = document.creamentEleent('script');
var url = params.url+'?callback' = + params.callback;
script.src=url;
document.body.appendChild(script)
}
function fn(data){
console.log(data)
}
jsonp({
url:'',
callback:fn
})
受同源策略的限制,无法跨域完成数据的请求,jsonp是解决跨域数据请求的一种方案。以百度为了,使用如下
<script src="https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?cb=jQuery110207811318019654161_1560908189983"></script>
<!--cb 是告诉后端,执行的回调函数名-->
<!--jQuery110207811318019654161_1560908189983 是回调函数名 -->
最终的返回结果如下:
jQuery110207811318019654161_1560908189983({"q":"","p":false,"bs":"","csor":"0","status":770,"s":[]});
然后就可以使用本地编写的回调函数进行数据的处理操作:
<script>
function jQuery110207811318019654161_1560908189983(data){
console.info(data);
// 数据处理
}
</script>
最终完整代码如下:
<script>
function jQuery110207811318019654161_1560908189983(data){
console.info(data);
// 数据处理
}
</script>
<!-- 这里可根据所需数据动态创建 -->
<script src="https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?cb=jQuery110207811318019654161_1560908189983"></script>
底层是引入一个script 标签,页面上创建script 标签。 简单实现
function jsonp(req){
var script = document.createElement('script');
var url = req.url + '?callback=' + req.callback.name;
script.src = url;
document.getElementsByTagName('head')[0].appendChild(script);
}
前端简单调用
function hello(res){
alert('hello ' + res.data);
}
jsonp({
url : '',
callback : hello
});
后端node 简单实现
var http = require('http');
var urllib = require('url');
var port = 8080;
var data = {'data':'world'};
http.createServer(function(req,res){
var params = urllib.parse(req.url,true);
if(params.query.callback){
console.log(params.query.callback);
//jsonp
var str = params.query.callback + '(' + JSON.stringify(data) + ')';
res.end(str);
} else {
res.end();
}
}).listen(port,function(){
console.log('jsonp server is on');
});
根据同源策略的限制,端口,域名,协议这三者 一个或者多个不同的情况下,就会出现跨域限制。 但是,标签访问跨域资源时,可以跨越这些同源策略限制,但是只能使用GET方法。 client.html 托管在8080端口,server.js托管在3000接口,模仿跨域操作 前台html发出跨域请求,并且传递一个本html中的回调函数的函数名 后台server.js获取函数名,并且把数据作为参数与函数名包装成一段JS返回前台, 前台执行返回的JS并且获得跨域数据。 JSONP是获取JSON的一种方式。 client.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Testing JSONP</title>
</head>
<body>
<script>
function b(data) {
console.log(data);
}
</script>
<!-- 负责解析字符串为 JavaScript 代码 -->
<script src="http://localhost:3000?callback=b"></script>
</body>
</html>
server.js
const http = require('http');
const url =require('url');
var data = { name: 'JodieZhang', password: '123456' };
const server = http.createServer((request, response) => {
var cb=url.parse(request.url,true).query.callback;
console.log(cb);
if (cb) {
response.writeHead(200, {
'Content-Type': 'application/json;charset=utf-8'
});
// 返回一段 JavaScript 代码
response.end( cb+"(" + JSON.stringify(data) + ")" );
}
});
server.listen(3000, () => {
console.log('The server is running at http://localhost:3000');
});
JSONP 是一种跨域请求方式,主要利用script 标签, 通过src请求服务器,利用回调函数,处理返回的数据。JSONP由 回调函数和数据组成,回调函数一般由浏览器编写,并随src请求中url,发给服务器端。
function foo () {
var dom = document.createElement('script')
dom.src='http://helloword.cn/login.php?callback=callback'
document.body.appendChild(dom)
}
function callback (res) {
console.log(res)
}
或者采用jQuery的ajax 方式
$.ajax({
url: 'http://helloword.cn/login.php',
type: 'GET',
datatype: 'jsonp',
jsonpCallback: 'callback'
})
服务端 login.php
<?php
$data = 'helloword'
$callBack = isset($_GET['callback'])? $_GET['callback'] : '';
echo $callback.'('.json_encode($data).')'
尽管浏览器有同源策略,但是 <script>
标签的 src
属性不会被同源策略所约束,可以获取任意服务器上的脚本并执行。jsonp
通过插入 script
标签的方式来实现跨域,参数只能通过 url
传入,仅能支持 get
请求。
function jsonp({url, params, callback}) {
return new Promise((resolve, reject) => {
//创建script标签
let script = document.createElement('script');
//将回调函数挂在 window 上
window[callback] = function(data) {
resolve(data);
//代码执行后,删除插入的script标签
document.body.removeChild(script);
}
//回调函数加在请求地址上
params = {...params, callback} //wb=b&callback=show
let arrs = [];
for(let key in params) {
arrs.push(`${key}=${params[key]}`);
}
script.src = `${url}?${arrs.join('&')}`;
document.body.appendChild(script);
});
}
使用:
function show(data) {
console.log(data);
}
jsonp({
url: 'http://localhost:3000/show',
params: {
//code
},
callback: 'show'
}).then(data => {
console.log(data);
});
服务端代码(node):
//express启动一个后台服务
let express = require('express');
let app = express();
app.get('/show', (req, res) => {
let {callback} = req.query; //获取传来的callback函数名,callback是key
res.send(`${callback}('Hello!')`);
});
app.listen(3000);
同源: URL是由协议、域名、端口号三部分组成。如果两个URL,他们的协议、域名、端口号都相同时,则代表他们是同源。
跨域:如果不满足同源,则就是跨域了。跨域就是从一个域去请求另一个域里面的资源。
同源策略:浏览器采用同源策略,来禁止页面加载或执行非本源的任何脚本。这样能够增加安全性。
script
、img
、iframe
、link
等含有src属性的标签不受同源测略的限制.
思路: 通过这些不受同源限制的元素,是否能解决这一问题?
jsonp({
url: 'http://localhost:3000/test',
success: function (result) {
console.log(result)
}
})
function jsonp(option) {
let callbackName = `_jsonp${Math.random().toString().substring(2)}`
window[callbackName] = function (result) {
option.success(result)
script.remove() // 将添加到页面中的script标签移除
}
if (option.url.includes('?')) {
option.url += `&callback=${callbackName}`
} else {
option.url += `?callback=${callbackName}`
}
let script = document.createElement('script')
script.src = option.url
document.body.appendChild(script)
}
Jsonp是实现跨域请求的一种方式,原理是利用 Githubissues.
同源协议指的是页面若域名,端口,协议都相同,便具有相同的源。 目的是为了保证用户信息的安全,防止恶意的网站窃取数据。
解决这种同源策略的方法便成为跨域。
JSONP是JSON with Padding的略称。允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问。
利用script标签的src属性调用资源不跨域的特性,向服务端请求同时传一个callback回调方法名作为参数,服务端接受函数名生成返回json格式资源的代码。