javascript --- [jsonp] script标签的妙用(绕过同源限制)

1. 同源

1.1 什么是同源

协议、域名、端口号相同

1.2 为什么有同源政策

同源政策是为了保护用户信息的安全,放置恶意的网站窃取数据。最初的同源政策是指A网站再客户端设置的Cookie,B网站是不能访问的.

随着互联网的发展,同源政策也越来越严格,在不同源的情况下,其中有一项规定就是无法向非同源地址发送Ajax请求,如果请求,浏览器就会报错

2. jsonp

  • jsonp是json with padding(将JSON数据作为填充内容)的缩写,它不属于Ajax请求,但它可以模拟Ajax请求。
  • 核心:利用了script标签可以向非同源端的服务器发送请求的特性,加载完毕后,相当于把服务器返回的内容当作JavaScript代码执行

2.1 准备工作

  • 准备2个服务器,一个监听3000端口(作为客户端),一个监听3001端口(作为服务端)
  • 两个服务器都暴露静态资源,3000端口服务器代码如下(3001端口类似):
const express = require('express')
const path = require('path')
const app = express()app.use(express.static(path.join(__dirname, 'public')))app.listen(3000, () => {console.log('http://localhost:3000')
})

2.2 JSONP的实现

1.在3001端口服务器中添加如下代码:

app.get('/jsonp',(req,res)=>{const data = `fn({name:'Marron', age:18, remarks:'JSONP测试'})`;res.send(data)
})

2.先定义一个全局函数,在使用script标签加载S2服务器的资源

<script>// 假设服务器返回的数据存储在data中function fn(data) {console.log(data);}
</script>
<!-- 使用jsonp加载资源 -->
<script src="http://localhost:3001/jsonp"></script>

2.3 JSONP代码优化

2.3.1 动态创建script标签发送jsonp请求

  • 实际项目中,不可能将script标签静态的写死…因此需要动态的创建script标签,用script标签的src的跨浏览器性,来发送请求.

1.客户端将函数名称传递到服务器端

<script src="http://localhost:3001/jsonp?cb=fn"></script>

2.将script请求的发送变成动态请求

<script>var srcipt = document.creatElement('script');script.src="http://localhost:3001/jsonp?cb=fn"document.body.appendChild(script);
</script>

3.发送请求后,删除掉script标签

<script>var srcript = document.createElement('script');script.src="http://localhost:3001/jsonp?cb=fn";document.body.appendChild(script);script.onload = function (){document.body.removeChild(script)} 
</script>

4.封装jsonp

function jsonp(url) {var script = document.createElement('script')script.src = urldocument.body.appendChild(script)script.onload = function() {document.body.removeChild(script)}
}

2.3.2 将回调函数封装进的JSONP

由于上面封装的JSONP它调用的函数和JSONP函数是分离的,破坏了JSONP的封装性,下面尝试将JSONP的回调函数封装如JSONP中,请求参数如下:

jsonp({url: 'http://localhost:3001/better?cb=fn',success: function(){}
})

产生了如下2个问题:

  • 回调函数不再是一个全局变量,即当使用script标签加载完毕只会,找不到回调函数
  • success是一个匿名函数,传递到后端是没有名称(如 fn)传递
// 将回调函数挂在到全局对象上
function jsonp(options) {var script = document.createElement('script');window.fn = options.success;script.src = options.url + '?cb=fn';document.body.appendChild(script)script.onload = function(){document.body.removeChild(script);window.fn = null;}
}

以上代码,当服务器端的返回的数据很慢时,如果连续发送多个不同的JSONP请求时,会导致多个请求的回调函数是同一个.

解决办法是,每次调用回调函数时,名字不能相同(即随机产生一个名字)

// 每次随机产生一个名字
function jsonp(options) {var script = document.createElement('script')var fn = 'fn'+ Math.random().toString().replace('.','')window[fn] = options.successscript.src = options.url + '?cb=' + fndocument.body.appendChild(script)script.onload = function() {document.body.removeChild(script)// 用完后释放内存delete window[fn]}
}

2.3.3 将get请求参数封装进jsonp

function jsonp(options) {var script = document.createElement('script')var fn ='fn' +Math.random().toString().replace('.', '')window[fn] = options.successvar params = []params.push('callback=' + fn)for (let attr in options.data) {params.push(attr + '=' + options.data[attr])}params = params.join('&')script.src = options.url + '?' + paramsdocument.body.appendChild(script)script.onload = function() {document.body.removeChild(script)delete window[fn]}
}

3. json实战

  • 使用上面封装好的jsonp去获取腾讯天气的代码

3.1 寻找api

  • 浏览器打开腾讯天气
  • 按F12打开调试工具,选择NetWork -> JS
    在这里插入图片描述
  • 可以看到此处域名(tianqi.qq.com)使用到了域名(wis.qq.com)的数据,产生了跨域,并且它传过去的参数含有callback字段.可以假设使用了JSONP技术进行跨域获取数据
    在这里插入图片描述

3.2 使用封装的JSONP函数获取数据.

  • 在3000端口的public目录下新建01.html,贴上如下代码.
<script>
jsonp({url: 'http://wis.qq.com/weather/common',data: {source: 'pc',weather_type: 'forecast_1h',province: '湖北省',city: '武汉市'},success: function(data) {if (data.status == 200 && data.message) {console.log(data);}}
})
</script>
  • 打开浏览器,输入localhost:3000/01.html.
    在这里插入图片描述
    在这里插入图片描述
    访问成功…嘻嘻.

4. 参考

源代码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/250346.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

不同权限访问详细细节

1 package com.package1;2 3 /**4 * 程序执行入口和调用方法在不同类但在同一个包中&#xff0c;除了private方法&#xff0c;其他任何权限的方法都可以都可相互调用5 * author Administrator6 *7 */8 public class Source {9 public static void main(String[] args) …

洛谷P2822组合数问题

传送门啦 15分暴力&#xff0c;但看题解说暴力分有30分。 就是找到公式&#xff0c;然后套公式。。 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std;long long read(){char ch;bool f false;wh…

基于Docker的GoldenGate部署

前言Docker最近几年异常火爆&#xff0c;主要是因为其方便、快捷、轻量&#xff0c;相对于VM&#xff0c;它不需要占用太多资源&#xff0c;随时可以创建、删除&#xff0c;或在已有image上添加一些软件&#xff0c;再制作成另一个模板image供日后使用。Docker提供的Hub或priva…

jquery --- 监听tab栏的变化

1. jQuery样式操作 1.1 操作css方法 参数只写属性名,则返回属性值(字符串) $(this).css(color)参数是 属性名、属性值(逗号分隔&#xff0c;则表示设置属性 $(this).css(color,red)参数可以是对象的形式 $(this).css({width: 400px,height: 400px })1.2 设置类样式方法 添…

算法 --- 递归实现多级树展开结构

说明 先根据数据渲染,然后再实现事件 渲染 在项目中,经常会给出一个深度不确定的数组,数字结构如下: data [{name: a, child:[{name: a1},{name: a2, child: [{name:a21}]}]},{name: b} ]要求将数组渲染成对应的目录结构, 结构如下: <ul><li>a<ul><…

ARP协议,以及ARP欺骗

1.定义&#xff1a; 地址解析协议&#xff0c;即ARP&#xff08;Address Resolution Protocol&#xff09;&#xff0c;是根据IP地址获取物理地址的一个TCP/IP协议。主机发送信息时将包含目标IP地址的ARP请求广播到网络上的所有主机&#xff0c;并接收返回消息&#xff0c;以此…

css --- [小结]让盒子水平垂直居中的解决方案

描述 有如下模型,想办法让 <style>.box{width: 500px;height: 500px;background: skyblue;} </style> <div class"box"><div class"inner"></div> </div>想办法让inner在box中水平垂直居中 方案1: 使用绝对定位 让…

作业3

import turtle turtle.bgcolor(red) turtle.color(yellow)turtle.fillcolor(yellow) turtle.begin_fill() for i in range(5):turtle.forward(100)turtle.right(144) turtle.end_fill() turtle.done()转载于:https://www.cnblogs.com/zhangkef97/p/9016608.html

分组查询

1、简单分组查询 语法形式&#xff1a; select function() from table_name where condition group by field; 进行分组查询时&#xff0c;分组所依据的字段上的值一定要有重复值&#xff0c;否则分组没有任何意义。 2、实现统计功能分组查询 关键字group by单独使用时&#xf…

深入探讨多模态模型和计算机视觉

近年来&#xff0c;机器学习领域在从图像识别到自然语言处理的不同问题类型上取得了显着进展。然而&#xff0c;这些模型中的大多数都对来自单一模态的数据进行操作&#xff0c;例如图像、文本或语音。相比之下&#xff0c;现实世界的数据通常来自多种模态&#xff0c;例如图像…

移动硬盘函数不正确要如何寻回资料

移动磁盘打不开函数不正确&#xff0c;是因为这个I盘的文件系统内部结构损坏导致的。要恢复里面的数据就必须要注意&#xff0c;这个盘不能格式化&#xff0c;否则数据会进一步损坏。具体的恢复方法看正文 工具/软件&#xff1a;AuroraDataRecovery 步骤1&#xff1a;先百度搜索…

HashMap的四种访问方式

第一种&#xff1a;通过Map.entrySet使用iterator遍历key和value 1 public void visit_1(HashMap<String,Integer> hm){ 2 Iterator<Map.Entry<String,Integer>> it hm.entrySet().iterator(); 3 while(it.hasNext()){ 4 Map.Entry<String ,Integer> …

C#/WPF程序开机自动启动

最近一个C/S项目客户要求开机自启的功能&#xff0c;网上找了一些方法&#xff0c;不顶用&#xff1b;最后自己去翻书&#xff0c;找到了这段代码&#xff0c;亲测可用&#xff0c;Wpf环境下需要改下获取程序目录的方式即可&#xff0c;Winform直接可用。 1 #regio…

记录一个坑

导入项目后运行控制台打印异常,pom都已检查,没有任何问题 解决办法: 项目右击---properties---deployment assembly---add---java build path entries---maven deoendencies 保存并关闭 解决... 这个问题第一次遇到 检查了很多遍maven的依赖,明明都已经配置好了 ,仍然产生了…

洛谷 P4011 孤岛营救问题【最短路+分层图】

题外话&#xff1a;昨夜脑子昏沉&#xff0c;今早一调试就过了...错误有&#xff1a;我忘记还有墙直接穿墙过...memset初始化INF用错了数...然后手残敲错一个状态一直过不了样例...要是这状态去比赛我简直完了......orz 题目链接&#xff1a;https://www.luogu.org/problemnew/…

微信小程序 --- [笔记小结] 环境搭建,基础学习

说明 源代码拷贝源代码 git clone https://github.com/Lizhhhh/miniProgram.git进入目录cd miniProgram查看tag: git tag选择需要查看的知识点,如: git checkout 02_Text 学习的视频失效了…后续还会找资源学习… 小程序 地址 一种不需要下载安装即可使用的应用,它实现了应…

tar压缩/解压用法

格式&#xff1a;tar zcvf 压缩后的路径及包名 你要压缩的文件 z:gzip压缩 c:创建压缩包 v:显示打包压缩解压过程 f:接着压缩 t:查看压缩包内容 x:解压 X:指定文件列表形式排除不需要打包压缩的文件或目录 -exclude:指定排除文件或目录不需要打包压缩的文件或目录&#xff08;也…

解决phpmyadmin 遇见的问题

1、phpmyadmin4.8.3 上传到网站目录后提示解决phpmyadmin mysqli_real_connect(): (HY000/2002): No such file or directory的错误&#xff0c; 解决方法把phpmyadmin目录中的配置文件config.sample.inc.php改成config.inc.php&#xff0c;并把 $cfg[Servers][$i][host] loc…

浅谈mysql

因为本地mysql服务的命名是mysql57&#xff0c;所以在终端启动和关闭mysql的时候&#xff0c;我们这么写&#xff0c; net stop mysql57 ;net start mysql57;如图所示 接着输入mysql -u -root -p&#xff1b; 然后输入自己的密码&#xff1b; 查看有多少个库 show database…

藤条生长为字母的动画

https://www.youtube.com/watch?vLshPEGiHsqc Blender Tutorial: Vine Animation Text 需要使用插件Add Curve: IvyGen, 进入用户设置,找到并沟选该插件. 建模:立体文字, [Alt C] 转换为网格mesh;选中网格文字,新建藤蔓:[Shift A], Curve\Add Ivy to Mesh左边工具栏下方的IvyG…