同源、跨域的概念与实现

news2024/11/28 11:37:14

本文将结合周老师的讲义对同源与跨域这一前端经典问题进行系统的总结、整理。一起来坐牢,快!

1. 同源限制

1.1 历史背景 - 含义的转变

1995年,同源政策由 Netscape 公司引入浏览器。目前,所有浏览器都实行这个政策。

最初,它的含义是指,A 网页设置的 Cookie,B 网页不能打开,除非这两个网页“同源”。所谓“同源”指的是“三个相同”。

  • 协议 - http://、https://、ftp://
  • 域名 - hostname
  • 端口号 - portnumber

举例来说,http://www.example.com/dir/page.html这个网址,协议是http://,域名是www.example.com,端口是80(默认端口可以省略),它的同源情况如下。

  • http://www.example.com/dir2/other.html:同源
  • http://example.com/dir/other.html:不同源(域名不同)
  • http://v2.www.example.com/dir/other.html:不同源(域名不同)
  • http://www.example.com:81/dir/other.html:不同源(端口不同)
  • https://www.example.com/dir/page.html:不同源(协议不同)

注意,标准规定端口不同的网址不是同源(比如8000端口和8001端口不是同源),但是浏览器没有遵守这条规定。实际上,同一个网域的不同端口,是可以互相读取 Cookie 的。

1.2 目的

同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。

设想这样一种情况:A 网站是一家银行,用户登录以后,A 网站在用户的机器上设置了一个 Cookie,包含了一些隐私信息。用户离开 A 网站以后,又去访问 B 网站,如果没有同源限制,B 网站可以读取 A 网站的 Cookie,那么隐私就泄漏了。更可怕的是,Cookie 往往用来保存用户的登录状态,如果用户没有退出登录,其他网站就可以冒充用户,为所欲为。因为浏览器同时还规定,提交表单不受同源政策的限制。

由此可见,同源政策是必需的,否则 Cookie 可以共享,互联网就毫无安全可言了。

同源是为了维护网站存储在客户端的临时信息的安全性,是客户端存储的网站信息的安全屏障。

1.3 限制范围

随着互联网的发展,同源政策越来越严格。目前,如果非同源,共有三种行为受到限制。

(1) 无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB。
(2) 无法接触非同源网页的 DOM。
(3) 无法向非同源地址发送 AJAX 请求(可以发送,但浏览器会拒绝接受响应)。

另外,通过 JavaScript 脚本可以拿到其他窗口的window对象。如果是非同源的网页,目前允许一个窗口可以接触其他网页的window对象的九个属性和四个方法。

九个对象window.closed、window.frames、window.length、window.location、window.opener、window.parent、window.self、window.top、window.window
四个方法window.blur()、window.close()、window.focus()、window.postMessage()

上面的九个属性之中,只有window.location是可读写的,其他八个全部都是只读。而且,即使是location对象,非同源的情况下,也只允许调用location.replace()方法和写入location.href属性。(只能进行简单的页面跳转)

虽然这些限制是必要的,但是有时很不方便,合理的用途也受到影响。故我们要使用一些技术去实现跨域。

一些小概念:

Q1:什么是网页的DOM?

A1:文档对象模型 (DOM) 是 HTML 和 XML 文档的编程接口。它提供了对文档的结构化的表述,并定义了一种方式可以使从程序中对该结构进行访问,从而改变文档的结构,样式和内容。DOM 将文档解析为一个由节点和对象(包含属性和方法的对象)组成的结构集合。简言之,它会将 web 页面和脚本或程序语言连接起来。

2.跨域的实现

2.1 降域实现部分跨域通信

Cookie 是服务器写入浏览器的一小段信息,只有同源的网页才能共享。如果两个网页一级域名相同,只是次级域名不同,浏览器允许通过设置document.domain共享 Cookie。

举例来说,A 网页的网址是http://w1.example.com/a.html,B 网页的网址是http://w2.example.com/b.html,那么只要设置相同的document.domain,两个网页就可以共享 Cookie。因为浏览器通过document.domain属性来检查是否同源。

也就是说如果两个页面均设置了这一js属性那么就可以实现一级域名相同的网页间的跨域请求。

下面我们呢通过一个具体的例子来实现这一操作。

2.1.1 环境搭建

我们利用apache的基于域名的虚拟主机技术来实现本次实验的环境搭建,这里大家可以配置一下。

1.配置网页目录
在这里插入图片描述
这些目录都需要创建,并在其内部写入首页文件index.html

2.apache配置文件
将下面的内容复制到D:\phpstudy_pro\Extensions\Apache2.4.39\conf\vhosts\default-default.conf文件内容去

<VirtualHost *:80>
	DocumentRoot "D:/phpstudy_pro/WWW/secbasic"
	ServerName www.security.com
    <Directory  "D:/phpstudy_pro/WWW/secbasic">
	        Options FollowSymLinks ExecCGI
			AllowOverride All
			Order allow,deny
			Allow from all
			Require all granted
			DirectoryIndex index.php index.html
	</Directory>
</VirtualHost>

#domain aaa
<VirtualHost *:80>
	DocumentRoot "D:/phpstudy_pro/WWW/aaa"
	ServerName www.aaa.com
    <Directory  "D:/phpstudy_pro/WWW/aaa">
	        Options FollowSymLinks ExecCGI
			AllowOverride All
			Order allow,deny
			Allow from all
			Require all granted
			DirectoryIndex index.php index.html
	</Directory>
</VirtualHost>

#domain bbb
<VirtualHost *:80>
	DocumentRoot "D:/phpstudy_pro/WWW/bbb"
	ServerName www.bbb.com
    <Directory  "D:/phpstudy_pro/WWW/bbb">
	        Options FollowSymLinks ExecCGI
			AllowOverride All
			Order allow,deny
			Allow from all
			Require all granted
			DirectoryIndex index.php index.html
	</Directory>
</VirtualHost>

#domain master.security.com
<VirtualHost *:80>
	DocumentRoot "D:/phpstudy_pro/WWW/master"
	ServerName master.security.com
    <Directory  "D:/phpstudy_pro/WWW/master">
	        Options FollowSymLinks ExecCGI
			AllowOverride All
			Order allow,deny
			Allow from all
			Require all granted
			DirectoryIndex index.php index.html
	</Directory>
</VirtualHost>

#domain slave.security.com
<VirtualHost *:80>
	DocumentRoot "D:/phpstudy_pro/WWW/slave"
	ServerName slave.security.com
    <Directory  "D:/phpstudy_pro/WWW/slave">
	        Options FollowSymLinks ExecCGI
			AllowOverride All
			Order allow,deny
			Allow from all
			Require all granted
			DirectoryIndex index.php index.html
	</Directory>
</VirtualHost>

3.配置本地host文件将域名解析到本地服务器上
C:\Windows\System32\drivers\etc\hosts
文件内容添加

127.0.0.1 slave.security.com
127.0.0.1 master.security.com 
127.0.0.1 www.security.com 
127.0.0.1 www.bbb.com 
127.0.0.1 www.aaa.com

4.小皮面板上重启apache进行测试
在这里插入图片描述
在这里插入图片描述

2.1.2 页面编写

master页面:index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>master</title>
</head>
<body>
    <h1>this is master.security.com</h1>
    <iframe id="001" src="http://slave.security.com"></iframe>
</body>

<script>
    //设置当前页面的域为本身的二级域名用于进行跨域通信
    document.domain = 'security.com';
    //抓取页面内部的ifram标签连接
    var ifr = document.getElementById("001");

    //等待加载完毕,将连接的窗口传递给win,取出内部的传输数据
    ifr.onload = function() {
        let win = ifr.contentWindow;
        alert(win.data);
    }

</script>
</html>

slave页面:index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>slave</title>
</head>
<body>
    <h1>this is slave.security.com</h1>
</body>
<script>
     document.domain = 'security.com';
     window.data = 'hello,i am slave';
</script>
</html>

2.1.3 测试

先关闭master页面的降域设置:
在这里插入图片描述
浏览器不允许进行跨域的数据交换,此时我们打开降域设置在此测试:
在这里插入图片描述
可以看到,master页面成功的获取了子页面的window.data全局变量。可以对其进行读取。

注意,这种方法只适用于 Cookie 和 iframe 窗口,LocalStorage 和 IndexedDB 无法通过这种方法规避同源政策,而要使用下文介绍 PostMessage API。

到此,降域进行跨域可以解决一部分问题。但很明显,实际环境中还会遇到很多域名不一致的跨域场景。那么就需要新的方法来解决了。

2.2 片段识别符实现跨域

片段标识符(fragment identifier)指的是,URL 的#号后面的部分,比如http://example.com/x.html#fragment#fragment。如果只是改变片段标识符,页面不会重新刷新。

也就是说我们可以利用这一特性,将片段识别符作为信息载体实现跨域。下面我们来尝试实现。

2.2.1 环境搭建

参照2.1.1的环境进行搭建,其实已经配置完毕了。我们的测试页面放在aaa文件夹和bbb文件夹内部,实现www.aaa.comwww.bbb.com两个域之间的跨域通信。

2.2.2 页面编写

aaa目录下的页面:
index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>aaa</title>
</head>
<body>
    <h1>this is www.aaa.com</h1>
</body>
<script>
    //创建ifram标签包含跨域通信目标网页
    let ifr = document.createElement('iframe');
    ifr.style.display = 'none';
    ifr.src = "http://www.bbb.com/index.html#data";
    document.body.appendChild(ifr);
    
    //输出数据
    function checkHash() {
        try {
        //获取数据去掉'#'
        let data = location.hash ? location.hash.substring(1) : ' ';
        console.log('获得到的数据是:', data);
        }catch(e) {
            console.log('咦,发生甚么事了?');
        }
    }
    window.addEventListener('hashchange', function(e) {
        checkHash();
        });
    </script>
</html>

01.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>this is 01.html,page for foward the message</h1>
</body>
<script>
	//将数据传递给父页面的父页面
    parent.parent.location.hash = self.location.hash.substring(1)
</script>
</html>

bbb目录下的页面:
index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>bbb</title>
</head>
<body>
    <h1>this is www.bbb.com</h1>
</body>
<script>
    //检查父页面的hash标识符,确认是否为请求数据的
    switch(location.hash) {
        case "#data":
        callback();
        break;
    }

    function callback() {
    const data = "this is a message from bbb.com";
    // parent.location.hash = data;
    try {
        //尝试直接向父页面的hash内写入数据
        parent.location.hash = data;
    }catch(e) {
        // 当前主流浏览器下的安全机制无法修改 parent.location.hash
        // 所以要利用一个中间的代理文件 iframe 
        var ifrproxy = document.createElement('iframe');
        ifrproxy.style.display = 'none';
        ifrproxy.src = 'http://www.aaa.com/01.html#' + data;     // 该文件在请求域名的域下
        document.body.appendChild(ifrproxy);
        }
       }
    </script>
</html>

2.2.3 测试效果

我们先在bbb域里面尝试直接修改该父页面:
在这里插入图片描述

在这里插入图片描述
这是因为在现在的安全内环境下,这种子页面修改父页面的hash标识符的行为在跨域情况下是被禁止的。我们的解决方案就是在下面添加进入一个中转页面,利用中转页面和父页面同源的特性,让中转页面实现数据的传递。

大概原理如下图:
在这里插入图片描述
说白了,bbb找了中间人帮忙给修改他爷爷的hash片段识别符。

修改代码之后在此进行测试:
在这里插入图片描述
跨域成功,但是这样操作的缺点显而易见。

缺点:

  • 数据直接暴露在了url中
  • 数据容量和类型都有限
  • 需要第三方中转实现麻烦

2.3 window.name

window.name(一般在js代码里出现)的值不是一个普通的全局变量,而是当前窗口的名字,要注意的是每个iframe都有包裹它的window,而这个window是top window的子窗口,而它自然也有window.name的属性,window.name属性的神奇之处在于name值在不同的页面(甚至不同域名)加载后依旧存在(如果没有修改则值不会变化),并且可以支持非常长的name值(2MB)

比如你在某个页面的控制台输入:

window.name = "hello world"
window.location = "http://www.baidu.com"

可以看到,跳转后也被保存了下来

在这里插入图片描述

示例:window.name实现跨域

aaa域文件:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>aaa</title>
</head>

<body>
    <h1>this is www.aaa.com</h1>
</body>
<script>
    let data = '';
    const ifr = document.createElement('iframe');
    ifr.src = "http://www.bbb.com";
    ifr.style.display = 'none';
    document.body.appendChild(ifr);

    //中转获取window.name
    ifr.onload = function() {
        //更换请求地址
        ifr.src = "http://www.aaa.com/01.html";
        //尝试取出window.name内的数据
        ifr.onload = function() {
            data = ifr.contentWindow.name;
            console.log('收到数据:', data);
        }
    }

    //此处为测试不进行中转
    // ifr.onload = function () {
    //     data = ifr.contentWindow.name;
    //     console.log('收到数据:', data);
    // }
</script>

</html>

01.html - 这个文件也可以为空,旨在提供一个可供bbb切换src的页面,用于制造同源访问。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>this is 01.html,page for foward the message</h1>
</body>
<script>
</script>
</html>

bbb域文件:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>bbb</title>
</head>
<body>
    <h1>this is www.bbb.com</h1>
</body>
<script>
    window.name = "传输的数据";
</script>
</html>

先尝试不设置中转页面是否可以获取子页面的data:
在这里插入图片描述
不允许,因为很显然aaa包含进了bbb,进行了跨域,并且window.name属性并未在限制范围之外。故一定会被同源策略禁止掉,我们可以采用二次修改src的方式,将bbb的window.name数值转移到本地同源的中转网页上,再传输进来。使用修改好的代码再次测试:

在这里插入图片描述
跨域成功。

2.4 window.postMessage()

上面的这种方法属于破解,HTML5 为了解决这个问题,引入了一个全新的API:跨文档通信 API(Cross-document messaging)。

这个 API 为window对象新增了一个window.postMessage方法,允许跨窗口通信,不论这两个窗口是否同源。举例来说,父窗口aaa.com向子窗口bbb.com发消息,调用postMessage方法就可以了。

postMessage方法的第一个参数是具体的信息内容,第二个参数是接收消息的窗口的源(origin),即“协议 + 域名 + 端口”。也可以设为*,表示不限制域名,向所有窗口发送。

示例1:新开页面之间的跨域通信

aaa域首页:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>aaa</title>
</head>

<body>
    <h1>this is www.aaa.com</h1>
</body>
<script>
    // 父窗口打开一个子窗口,取名title
    var popup = window.open('http://www.bbb.com', 'title');
    // 父窗口向子窗口发消息
    popup.postMessage('Hello, i am aaa page,who are you ?', 'http://www.bbb.com');

   // 监听 message 消息
   window.addEventListener('message', function (e) {console.log(e.data);}, false);

</script>

</html>

bbb域首页

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>bbb</title>
</head>
<body>
    <h1>this is www.bbb.com</h1>
</body>
<script>
        //子窗口向父窗口发送消息
        window.opener.postMessage('hello nice to meet you , my name is bbb', 'http://www.aaa.com');
        // 监听 message 消息
        window.addEventListener('message', function (e) {console.log(e.data);}, false);
</script>
</html>

测试效果:
在这里插入图片描述
在这里插入图片描述
可以看到其在新的窗口内进行了跨域通信。但是正常使用的时候弹出一个新页面并不常见。更多的还是使用iframe对页面进行嵌套处理,在使用postmessage实现平滑的跨域通信。

一些概念:

message事件的参数是事件对象event,提供以下三个属性。

  • event.source:发送消息的窗口
  • event.origin: 发送消息的网址(发送者地址)
  • event.data: 消息内容

示例2:结合iframe的跨域

aaa域页面:index.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>aaa</title>
</head>

<body>
    <h1>this is aaa page</h1>
    <iframe src="http://www.bbb.com" ></iframe>
</body>
<script>

    window.onload = function () {
        let targetOrigin = 'http://www.bbb.com';
        //想要操作当前iframe的时候,就像该ifranme中postMessage()一个东西。
        window.frames[0].postMessage('来自aaa大哥的轮船~~~', targetOrigin );
        //*表示任何域都可以监听。
    }
    //当我监听到message事件的时候,我就知道有人向我发送数据了,我获得了数据就可以做对应的事情。内部对消息做处理
    window.addEventListener('message', function (e) {
        console.log('aaa 接收到的消息:', e.data);
    });
</script>

</html>

bbb域页面:index.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>bbb</title>
</head>

<body>
    <h1>this is www.bbb.com</h1>
</body>
<script>
    //创建事件监听器,监听message,第二个参数内写上处理函数
    window.addEventListener('message', function (e) {
        //判断消息来源为自己的父页面,防止恶意信息传输
        if (e.origin !== 'http://www.aaa.com') {
            return;
        }
        console.log('message.source: ', e.source);
        console.log('message.origin: ', e.origin);
        console.log('bbb 接收到的消息:', e.data);
        parent.postMessage('来自bbb大哥的火箭^|^', e.origin);
    })
</script>

</html>

效果测试:
在这里插入图片描述

示例3:结合LocalStorage实现跨域

通过window.postMessage,读写其他窗口的 LocalStorage 也成为了可能。

大概的思路就是让子页面通过postmessage给父页面提供操作子页面LocalStorage小小数据库的接口。从而在子页面LocalStorage内实现和子页面的共享数据以进行跨域通信。

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

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

相关文章

爬虫代理Scrapy框架详细介绍4

Scrapy 框架 Scrapy实例 下载安装 pip install scrapy Hello World 创建工程 在 cmd 下切换到想创建 scrapy 项目的地方&#xff0c;然后使用命名 scrapy startproject tutorial 注&#xff1a;tutorial 为工程名 然后就会发现在当前位置会多出一个文件夹&#xff0c;名字是 tu…

C++——map|set介绍

目录 关联式容器 set set的构造 set的迭代器 set的容量 set修改操作 equal_range multiset map map的构造 map的迭代器 map的容量与元素访问 map测试 关联式容器 在初阶阶段&#xff0c;我们已经接触过STL中的部分容器&#xff0c;比如&#xff1a;vector、list、…

Linux内核权限提升漏洞

SSRF检测的一些思考 DNS平台没有立刻收到请求&#xff0c;是在之后的某个时间段收到了不同的请求信息&#xff0c;这至少表明了一点&#xff0c;此处存在有无回显的SSRF&#xff0c;虽然想要证明有更大的危害比较困难&#xff0c;但是至少说明了存在有SSRF的风险&#xff0c;所…

Maven 命令之将本地 Jar 包安装到 Maven 本地仓库

1、前言 Maven 是 Java 平台下的一款项目构建和依赖管理的自动化管理工具。 通过 Maven 远程仓库地址我们可以方便的管理 Jar 依赖包&#xff0c;但是在实际项目中有时候存在远程仓库中没有的 Jar 包&#xff0c;我们在项目中又必须要使用它&#xff0c;那就需要把本地 Jar 添…

HC-SR04超声波传感器使用

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录前言一、关于HC-SR04二、使用步骤1.确保驱动已经安装2.安装GPIO工具3.安装GPIO的Python支持4.Python3代码总结前言 最近在做一个项目&#xff0c;需要用到超声波传感…

誉辰智能拟科创板上市:欲募资4亿元,毛利率、研发费用率均下滑

近日&#xff0c;深圳市誉辰智能装备股份有限公司&#xff08;下称“誉辰智能”&#xff09;在上海证券交易所更新招股书&#xff08;申报稿&#xff09;&#xff0c;披露时间为2023年1月7日&#xff0c;准备在科创板上市。据贝多财经了解&#xff0c;誉辰智能曾于2022年6月29日…

解决SpringBoot项目整合Sharding-JDBC后启动慢的问题

一、问题描述线上某一项目以jar包的方式发布&#xff0c;需要健康检查&#xff0c;若15次健康检查页面状态均为非200则健康检查失败&#xff0c;就会导致tomcat服务加载失败。前几天版本迭代&#xff0c;发布该项目时&#xff0c;因最后一次健康检查的时间比启动完成时早&#…

练习时长两年半的tcp三次握手

1、TCP是什么&#xff1f;TCP是面向连接的协议&#xff0c;它基于运输连接来传送TCP报文段&#xff0c;TCP运输连接的建立和释放&#xff0c;是每一次面向连接的通信中必不可少的过程。TCP运输连接有以下三个阶段&#xff1a;建立TCP连接&#xff0c;也就是通过三报文握手来建立…

Oracle打补丁

oralce打补丁 打补丁前提&#xff1a; 一、备份数据库 二、将oracle服务全部停掉 1、查看opatch的版本号 1.1、环境变量配置ORACLE_HOME 1.2、运行opatch version命令&#xff0c;查看opatch的版本号 备注&#xff1a;网上查看opatch的版本号对应的oracle是否匹配&#xff0c;…

【分治策略】查询中位数最接近点对

查询中位数给定线性序集中n个元素和一个整数k 【k(n1)/2】&#xff0c;要求找出这n个元素中第k小的元素&#xff0c;即找中位数。线性序列没有排序,没有重复值。已知快速排序划分时一个划分基准数的位置在确定后&#xff0c;在之后排序中是不会变的。利用此特性&#xff0c;以下…

dataphin如何使用zip文件,离线安装python第三方包?

好久没写文章啦&#xff0c;快过年了啦&#xff0c;打工人要回家啦 背景介绍&#xff1a; 每次在dataphin里使用pandas的时候&#xff0c;都要pip install pandas。dataphin需要下载pandas安装包&#xff0c;比较费时。总而言之&#xff0c;这种方式慢。 所以我要在dataphin的…

【手写 Vue2.x 源码】第十四篇 - 生成 ast 语法树 - 模板解析

一&#xff0c;前言 上篇&#xff0c;主要介绍了生成 ast 语法树-正则说明部分&#xff0c;涉及以下几个点&#xff1a; 简要说明了 HTML模板的解析方式对模板解析相关正则说明和测试 本篇&#xff0c;生成 ast 语法树-代码实现 二&#xff0c;模板解析 模板解析的方式&…

22. 听说你想要用爬虫采集我的手机号?哎 ~ 我展示用的是图片

本篇博客我们实现图片渲染手机号码案例&#xff0c;用于防止爬虫直接采集文字信息。 爬虫训练场 本案例实现的效果如下所示 文章目录bootstrap5 实现名片样式卡片补充数据生成逻辑生成用户 5 个汉字的昵称调用头像 API&#xff0c;生成图片将手机号码生成图片bootstrap5 实现名…

菜鸡二次封装element中table表单

实现效果如下封装的table表单<template><el-table:span-method"arraySpanMethod":header-cell-style"rowClass":cell-style"cellStyle":data"tableData"style"width: 100%; height: 100%">//暂无数据展示<te…

汤姆斯的天堂梦(C++,Dijkstra)

题目描述 汤姆斯生活在一个等级为 000 的星球上。那里的环境极其恶劣&#xff0c;每天 121212 小时的工作和成堆的垃圾让人忍无可忍。他向往着等级为 NNN 的星球上天堂般的生活。 有一些航班将人从低等级的星球送上高一级的星球&#xff0c;有时需要向驾驶员支付一定金额的费…

【跟月影学可视化】学习笔记 41 篇(完结)

说明 【跟月影学可视化】专栏学习笔记。 个人学习笔记源码&#xff1a;https://github.com/kaimo313/visual-learning-demo 一共做了 162 个学习示例以及 41 篇博客学习笔记&#xff0c;要深入学习该课程请支持正版&#xff0c;个人笔记仅供参考。 笔记目录 【图形基础篇…

什么是无源相干定位系统?

无源定位&#xff08;Passive Localization&#xff09;不通过发射信号来探测目标的位置&#xff0c;而是接收目标的有意、无意辐射或反射信号来实现对侦察目标的探测、定位与追踪。接收的信号可以是目标直接辐射的信号&#xff0c;也可以是外辐射源照射到目标后反射或散射的信…

网站关键词怎么优化排名(网站关键词通常可以选择哪些词)

网站核心关键词的选取需要具备哪些条件 在对网站优化的过程中&#xff0c;肯定少不了对网站关键词的选取&#xff0c;关键词的选择又是网站优化中十分重要的一步&#xff0c;那么网站在选择关键词的过程中需要遵循哪些原则呢&#xff1f;关于这个问题老张带你了解一下。 1、首…

wav文件格式分析与详解

wav文件格式分析与详解WAV文件是在PC机平台上很常见的、最经典的多媒体音频文件,最早于1991年8月出现在Windows 3.1操作系统上,文件扩展名为WAV,是WaveFom的简写,也称为波形文件,可直接存储声音波形,还原的波形曲线十分逼真。WAV文件格式简称WAV格式是一种存储声音波形的数字音…

Wijmo 2022 v2 JavaScript UI Crack

Wijmo 2022 v2 采集 by Ω578867473 添加对 Angular 14 和 React 18 的支持以及对 FlexGrid 和 FlexChart 的改进。特征 Angular 14 支持——您今天就可以开始将 Angular 14 应用程序与 Wijmo 结合使用。Wijmo 提供了大量快速、灵活的 Angular 组件&#xff0c;每个组件都有丰富…