手写jsonp

237 阅读1分钟
jsonp原理

一些标签本身具备跨域能力, jsonp利用了<script>标签的src属性实现跨域,发送GET请求

风险
  1. 回调函数的函数名可以自定义,如果callbackName为另一个script标签,将会导致后面的恶意代码执行
  2. CSRF攻击:jsonp跨域发送请求,通过callback获取用户的隐私信息。解决:设置token
实现思路
  1. 动态创建一个script标签
  2. 设置script标签的src属性为url,设置回调函数处理返回的数据
实现步骤
  1. 定义一个jsonp函数,传入参数为url,请求携带参数params,回调函数名callbackName

  2. jsonp函数内部需要完成两件事情,一个是拼接url,params,callbackName为完整路径,二是返回一个promise对象

  3. promise中完成jsonp跨域

    1)创建一个script标签

    2)将拼接好的url设置为script标签的src属性

    3)将script标签添加到dom中

    4)处理callback执行结果,请求成功后删除添加的script

代码实现
        //手写jsonp,函数中传入参数,url,params,callbackName
        function jsonp({ url, params, callbackName }) {
            //定义一个函数拼接url字符串
            function getUrl() {
                //遍历params对象中的键值对,拼接到callbackName前面
                let dataSrc = ''
                for (let key in params) {
                    if (params.hasOwnProperty(key)) {
                        dataSrc += `${key}=${params[key]}&`

                    }

                }
                //拼接callback
                dataSrc+=`callBack=${callbackName}`
                //拼接url
                return `${url}?${dataSrc}`
            }
            return new Promise((resolve,reject)=>{
                //首先创建一个script标签
                var scriptEle = document.createElement('script');
                //修改script标签的src属性
                scriptEle.src = getUrl;
                //把节点放到文档中 
                document.body.appendChild(scriptEle);
                //处理回调函数
                window[callbackName] = data=>{
                    resolve(data);
                    //删除script标签
                    document.removeChild(scriptEle);
                }
            })
        }