GithubHelp home page GithubHelp logo

Comments (17)

into-piece avatar into-piece commented on May 31, 2024 5

同源策略

同源协议指的是页面若域名,端口,协议都相同,便具有相同的源。
目的是为了保证用户信息的安全,防止恶意的网站窃取数据。
解决这种同源策略的方法便成为跨域。

JSONP

JSONP是JSON with Padding的略称。允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问。

原理

利用script标签的src属性调用资源不跨域的特性,向服务端请求同时传一个callback回调方法名作为参数,服务端接受函数名生成返回json格式资源的代码。

实现

<script type="text/javascript">
    // 获取到跨域资源后的回调
    var handleFn = function(data){
        console.log(data)  // JSONP跨域成功返回的资源
    };
    var url = "resource-url?callback=handleFn";
    var script = document.createElement('script');
    script.setAttribute('src', url);
    document.getElementsByTagName('head')[0].appendChild(script); 
</script>
// 服务端
handleFn({
    "date": "2019-6-18",
    "slogan": "夕夕姐真好看",
    "content": "稳坐沙发" 
});

from step-by-step.

YvetteLau avatar YvetteLau commented on May 31, 2024 1

尽管浏览器有同源策略,但是 <script> 标签的 src 属性不会被同源策略所约束,可以获取任意服务器上的脚本并执行。jsonp 通过插入 script 标签的方式来实现跨域,参数只能通过 url 传入,仅能支持 get 请求。

实现原理:

  • Step1: 创建 callback 方法
  • Step2: 插入 script 标签
  • Step3: 后台接受到请求,解析前端传过去的 callback 方法,返回该方法的调用,并且数据作为参数传入该方法
  • Step4: 前端执行服务端返回的方法调用

jsonp源码实现

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);

from step-by-step.

ivan0525 avatar ivan0525 commented on May 31, 2024 1

什么是同源策略?

同源: URL是由协议域名端口号三部分组成。如果两个URL,他们的协议、域名、端口号都相同时,则代表他们是同源。

跨域:如果不满足同源,则就是跨域了。跨域就是从一个域去请求另一个域里面的资源。

同源策略:浏览器采用同源策略,来禁止页面加载或执行非本源的任何脚本。这样能够增加安全性。

浏览器中有哪些元素不受同源策略的限制呢?

scriptimgiframelink等含有src属性的标签不受同源测略的限制.

如何解决跨域问题?

思路: 通过这些不受同源限制的元素,是否能解决这一问题?

jsonp实现

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)
}

from step-by-step.

KRISACHAN avatar KRISACHAN commented on May 31, 2024

JSONP(JSON with Padding)是数据格式JSON的一种“使用模式”,可以让网页从别的网域要数据。另一个解决这个问题的新方法是跨来源资源共享。

由于同源策略,一般来说位于server1.example.com的网页无法与 server2.example.com的服务器沟通,而HTML的 <script>元素是一个例外。利用 <script>元素的这个开放策略,网页可以得到从其他来源动态产生的JSON数据,而这种使用模式就是所谓的 JSONP。用JSONP抓到的数据并不是JSON,而是任意的JavaScript,用 JavaScript解释器运行而不是用JSON解析器解析。

配合后端的前端实现

 <script type="text/javascript"
         src="http://server2.example.com/RetrieveUser?UserId=1823&jsonp=parseResponse">
 </script>

from step-by-step.

shenanheng avatar shenanheng commented on May 31, 2024
  • jsonp的原理
    script标签中的src属性并没有同源策源的限制,并且只能用于get请求
function jsonp() {
    return new Promise((resolve, reject) => {
      var fn = data => {
        if (data.code === 200) {
          resolve(data);
        } else {
          reject(data);
        }
      };
      var script = document.createElement("script");
      script.src = "url?callback=fn";
      document.body.append(script);
    });
  }

from step-by-step.

zhujunwei avatar zhujunwei commented on May 31, 2024

JSONP是受限于浏览器的同源策略的一种跨域解决方案,
主要就是实现方式,就是通过动态创建script标签:

function createJSONP(url, callback) {
      var script = document.createElement("script");
      script.src = "url?callback=callback";
      document.body.append(script);
}

优点:兼容性好,实现比较简单
缺点:只能发送get请求,响应失败没有状态码, 数据容易被劫持

from step-by-step.

Liruimin2 avatar Liruimin2 commented on May 31, 2024

jsonp主要利用script标签的src属性,指向一个需要访问的地址并提供一个回调函数来接收。

<script src="http://地址"></script> <script> function jsonp(data){ console.log(data)} </script>

from step-by-step.

riluocanyang avatar riluocanyang commented on May 31, 2024

JSONP原理及简单实现

JSONP原理

JSONP是解决跨域问题的一种方案,原理如下:
1、利用script标签的src属性实现跨域;
2、然后前端将回调函数作为参数传给服务器,服务器注入参数后再返回。

JSONP简单实现

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
})

from step-by-step.

chongyangwang avatar chongyangwang commented on May 31, 2024

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
 })

from step-by-step.

woyiweita avatar woyiweita commented on May 31, 2024

受同源策略的限制,无法跨域完成数据的请求,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>

from step-by-step.

hoyong6 avatar hoyong6 commented on May 31, 2024

底层是引入一个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');
});

from step-by-step.

jodiezhang avatar jodiezhang commented on May 31, 2024

根据同源策略的限制,端口,域名,协议这三者 一个或者多个不同的情况下,就会出现跨域限制。
但是,<script>标签访问跨域资源时,可以跨越这些同源策略限制,但是只能使用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');
});

image

from step-by-step.

yelin1994 avatar yelin1994 commented on May 31, 2024

JSONP

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).')'

from step-by-step.

AILINGANGEL avatar AILINGANGEL commented on May 31, 2024

Jsonp是实现跨域请求的一种方式,原理是利用<script>标签的src属性不受同源策略限制的特点,来发送跨域请求。

  1. 声明一个回调函数
  2. 创建一个包含回调函数名称的url地址
  3. 服务器端接收到这个请求,根据url地址中的参数获取到回调函数的名称,然后将数据传递给回调函数,返回这个回调函数的调用给前端
  4. 浏览器拿到包含数据的回调函数的调用,并执行这个代码
function callback(data) {
    //do something with data
}

function jsonpFunc(url, cb) {
    let script = document.createElement('script');
    script.src = url + '?cb=' + cb;
    document.body.appendChild(script);
}

jsonpFunc('http://your.domain.com', callback);

from step-by-step.

MissNanLan avatar MissNanLan commented on May 31, 2024
// 实现
function jsonp({ url, params, callback }) {
    return new Promise((resolve, reject) => {
        var script = document.createElement('script');
        window[callback] = function (data) {
            resolve(data);
            document.body.removeChild(script);
        }

        params = { ...params, callback };
        let arrs = [];

        for (let key in params) {
            arrs.push(`${key} = ${params[key]}`);
        }
        // 2. 创建script标签
        script.src = `${url}?${arrs.join('&')}`;
        // http:// localhost:3000/show?callback=fn
        docuemnt.getElementsByTagName('head')[0].appendChild(script)
    })
}

// 使用
function fn(data) {
    console.log(data)
}

jsonp({
    url: 'http://localhost:300/show',
    params: {},
    callback: 'fn'  // 1. 创建callback 的方法
}).then(data => {
    console.log(data);
})

// 服务器端
let express = require('express');
let app = express();
app.get('/show', (req, res) => {
    let { callback } = req.query;
    res.send('hello')
})
app.listen(3000)

参考艳姐姐

from step-by-step.

zangbianxuegu avatar zangbianxuegu commented on May 31, 2024
// 实现
function jsonp({ url, params, callback }) {
    return new Promise((resolve, reject) => {
        var script = document.createElement('script');
        window[callback] = function (data) {
            resolve(data);
            document.body.removeChild(script);
        }

        params = { ...params, callback };
        let arrs = [];

        for (let key in params) {
            arrs.push(`${key} = ${params[key]}`);
        }
        // 2. 创建script标签
        script.src = `${url}?${arrs.join('&')}`;
        // http:// localhost:3000/show?callback=fn
        docuemnt.getElementsByTagName('head')[0].appendChild(script)
    })
}

// 使用
function fn(data) {
    console.log(data)
}

jsonp({
    url: 'http://localhost:300/show',
    params: {},
    callback: 'fn'  // 1. 创建callback 的方法
}).then(data => {
    console.log(data);
})

// 服务器端
let express = require('express');
let app = express();
app.get('/show', (req, res) => {
    let { callback } = req.query;
    res.send('hello')
})
app.listen(3000)

参考艳姐姐

服务端 res.send 少了 callback 吧?

from step-by-step.

zangbianxuegu avatar zangbianxuegu commented on May 31, 2024

尽管浏览器有同源策略,但是 <script> 标签的 src 属性不会被同源策略所约束,可以获取任意服务器上的脚本并执行。jsonp 通过插入 script 标签的方式来实现跨域,参数只能通过 url 传入,仅能支持 get 请求。

实现原理:

  • Step1: 创建 callback 方法
  • Step2: 插入 script 标签
  • Step3: 后台接受到请求,解析前端传过去的 callback 方法,返回该方法的调用,并且数据作为参数传入该方法
  • Step4: 前端执行服务端返回的方法调用

jsonp源码实现

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);

使用中的 function show 没必要了吧?

from step-by-step.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.