下一个泡泡玛特工程师是谁呢?

收集一些自己用到的prompt

2023-04-05 · 1 min read

机械键盘相关参数

机械键盘相关参数记录

2023-04-05 · 1 min read

Web 前端性能优化

常用的web前端性能优化手段

2023-03-19 · 3 min read

Blender常用快捷键

自己经常用到的一些快捷键记录

2022-12-11 · 1 min read

Docker 常用命令

精简 Docker 常用命令

2022-11-06 · 1 min read

项目管理

项目管理相关知识

2022-11-06 · 1 min read

JS沙箱sandbox的各种实现

我们把Js隔离机制常常称作沙箱

2022-09-18 · 1 min read

Amazing!Solid 比react还react

今天来介绍2个amazing的东东

2022-09-12 · 1 min read

puppeteer应用

使用傀儡师来操作浏览器这个傀儡吧

2022-09-11 · 1 min read

做一个web termianl

前端react, 后端nodejs, 直接可用版web termianl

2022-07-17 · 1 min read

TypeScript里常用的工具类型

经常用到的工具类型,提取抽离出来,供以后复用

2022-06-26 · 1 min read

Vim大法好

想要丢掉鼠标,试试Vim

2022-06-26 · 1 min read

碧血丹心

无论时光如何沾染风霜,也永似红日光

2022-05-10 · 1 min read

chrome V8 引擎中的垃圾回收机制

V8引擎就是nodejs的发动机

2022-03-03 · 1 min read

如何开发一个cli

命令行交互界面是程序员必备的工具,如何开发一个呢?

2022-02-21 · 1 min read

Javascript中的哲学

道生一,一生二,二生三,三生万物

2022-02-20 · 1 min read

React Redux 实现 (Context 版)

React Redux 实现 (Context 版)

2022-02-16 · 1 min read

mobx-react 使用

虽然不常用,但是可以学一下

2022-02-16 · 1 min read

Less中的for和forEach循环

循环的使用是保持代码干燥和避免重复的好方法

2022-02-15 · 1 min read

Webpack Splitchunks 详解

webpack 优化

2022-02-15 · 1 min read

ssh-keygen命令详解

为ssh生成、管理和转换认证密钥

2022-02-15 · 1 min read

使用CURL发送POST请求

curl 是常用的命令行工具,用来请求 Web 服务器。

2022-02-15 · 1 min read

Webpack Plugin 开发

让我们来学一下如何开发一个webpack插件

2022-02-14 · 1 min read

JS 实现两个大数相加?

algo-adding-large-numbers

2022-02-10 · 1 min read

字典树 trie

字典树 trie

2022-02-09 · 1 min read

浏览器原理问题

浏览器原理问题

2022-01-11 · 1 min read

MacBook快速进入一个文件夹目录

mac如何快速进入一个文件夹

2021-10-26 · 1 min read

react合成事件

react-synthetic-event

2021-10-25 · 1 min read

mini webpack实现

通过babel核心来实现迷你版的webpack

2021-10-10 · 1 min read

设计模式

在程序设计中有很多实用的设计模式,而其中大部分语言的实现都是基于类

2021-10-10 · 1 min read

babel核心

babel核心介绍

2021-10-07 · 1 min read

React 15 和 React 16 的区别

react-15-16

2021-10-06 · 1 min read

React性能优化

浅谈react性能优化的方法

2021-10-05 · 1 min read

交通信号灯实现

如何用js来实现交通信号灯呢

2021-09-25 · 1 min read

内存管理

前端中的内存管理

2021-09-25 · 1 min read

前端安全

前端关于安全方面的知识

2021-09-25 · 2 min read

网络和并发

http各版本对于并发的支持,前端如何控制并发量?

2021-09-25 · 1 min read

跨域方法

总结了9种跨域方法

2021-09-24 · 1 min read

react virtualList 虚拟列表无限滚动实现

用react实现虚拟滚动

2021-09-16 · 1 min read

监控埋点方案

前端监控埋点方案

2021-09-16 · 1 min read

Mini useEffect实现

如何实现useEffect?

2021-09-11 · 1 min read

Mini useState 实现

我们来思考一下useState是怎么实现的呢?

2021-09-11 · 1 min read

React Fiber

react-fiber

2021-09-11 · 1 min read

React class组件和function组件异同

类组件和函数组件有何相同点有何不同点呢?

2021-09-11 · 1 min read

Lodash Get 实现

algo-lodash-get

2021-09-08 · 1 min read

手写reduce实现

algo-reduce

2021-09-08 · 1 min read

Hooks 原理概览

react-hooks

2021-09-05 · 1 min read

Hook原理——状态Hook

react-hook-state

2021-09-05 · 1 min read

手写Mini Redux实现

手写一个简易版的redux实现,包含了核心逻辑

2021-09-04 · 1 min read

legacy和concurrent模式

react-legacy-concurrent

2021-09-01 · 1 min read

react架构

总体 react 的核心可以用 ui=fn(state)来表示 3 大核心对象、3 大核心阶段、2 大工作循环 Scheduler(调度器): 排序优先级,让优先级高的任务先进行 reconcile Reconciler…

2021-09-01 · 2 min read

react核心api和jsx

为什么要有jsx,为什么会有虚拟bom

2021-09-01 · 1 min read

setState是同步的还是异步的

react-setstate-usestate

2021-08-31 · 1 min read

如何使用NodeJs创建HTTP服务?

如何使用NodeJs创建HTTP服务?

2021-08-17 · 1 min read

NodeJS 事件循环模型

nodejs-eventloop

2021-08-11 · 2 min read

Buffer

nodejs中的内存管理

2021-08-10 · 1 min read

微前端解决方案-qiankun

目前国内最好的微前端解决方案-qiankun

2021-08-10 · 1 min read

React Mini版实现(1)

学一门技术最好的方法就是做一个其玩具版的实现,我们来尝试实现一下react和react-dom最简单版本吧

2021-08-04 · 1 min read

brew安装

brew 是 MacOS 上的包管理工具,可以简化 macOS 和 Linux 操作系统上软件的安装。

2021-08-04 · 1 min read

CommonJS简易版实现

CommonJS我们经常用,如何实现一个简易版的commonJS呢?

2021-08-01 · 1 min read

极品透明Dashboard样式分享

一个极品透明Dashboard样式分享

2021-07-30 · 1 min read

Stream

nodejs中的流

2021-07-11 · 1 min read

NodeJS全局对象

JavaScript 中有一个特殊的对象,称为全局对象(Global Object),它及其所有属性都可以在程序的任何地方访问,即全局变量。

2021-05-18 · 1 min read

如何部署Nodejs服务

如何快速的部署一个Nodejs服务到公网呢?

2021-05-12 · 1 min read

Events

events模块是node的核心模块之一,几乎所有常用的node模块都继承了events模块,比如http、fs等。

2021-05-11 · 1 min read

用JS绘制背景,让CSS直接使用 'background:paint(xxx)'

CSS对象新特性,新的background设置方式

2021-04-30 · 1 min read

Block Formatting Context 块级格式化上下文

可以将BFC看成是元素的一种属性,拥有了这种属性的元素就会使他的子元素与世隔绝,不会影响到外部其他元素

2021-04-17 · 1 min read

如何使用Nodejs来创建一个TCP/UDP服务?

如何使用Nodejs来创建一个TCP/UDP服务?

2021-04-17 · 1 min read

Mac使用tree生成目录结构

程序员经常会有需求,需要列出项目的结构树。Mac或者Linux下可以使用tree列出项目结构

2021-04-04 · 1 min read

常见算法

一些比较常见算法

2021-03-20 · 1 min read

前端缓存

对于性能优化离不开缓存

2021-02-28 · 1 min read

前端答疑

一些比较常见的问题

2020-09-02 · 1 min read

Nodejs 网络 & HTTP

nodejs-network

2020-08-14 · 1 min read

JavaScript AST 抽象语法树

源代码的抽象语法结构的树状表现形式

2020-08-02 · 1 min read

nodejs里面向切面编程的一种范式

在一些场景下我们可能需要一种面向切面的编程方式

2020-08-01 · 1 min read

各种JS模块化特性

AMD、CMD、CJS、ESM

2020-05-30 · 1 min read

手写Ajax实现

使用HMR一步步实现Ajax

2020-05-30 · min read

手写PromiseA+实现

如何自己实现promiseA+规范,手写一个promise实现

2020-04-30 · 1 min read

debug和内存泄露

nodejs的debug方法

2020-04-08 · 1 min read

Javascript prototype 原型链

js-prototype

2019-09-07 · 1 min read

this指针、作用域

this是在执行时动态读取上下文决定的,不是在定义时决定

2019-06-14 · 1 min read

call、apply、bind的极简实现

使用symbol实

2019-06-03 · 1 min read

CSS联合选择器区分列表元素个数不同所要求的不同样式

对于列表,在有些时候针对于不同个数的item会有不同的显示,比如col份数,用js固然可以,是否可以用css更简便的实现呢?

2019-04-30 · 1 min read

TypeScript基础

介绍TypeScript基础知识

2019-04-30 · 1 min read

JS中的变量提升

为什么js当时要这样设计

2019-03-07 · 1 min read

ES6之Class

关于ES6里的class, 我们有什么不知道的事?

2019-03-01 · 1 min read

HTTP详解

HTTP协议(HyperText Transfer Protocol,超文本传输协议)是用于从WWW服务器传输超文本到本地浏览器的传输协议

2019-02-17 · 2 min read

极简代码实现节流Throttle和防抖Debounce

使用各9行代码实现节流和防抖函数

2019-01-30 · 1 min read

Javascript 事件循环 EventLoop

js-eventloop

2018-09-07 · 1 min read

POST和GET区别

POST和GET区别是什么呢?

2018-08-14 · 1 min read

正则表达式

正则表达式一锅端

2018-07-30 · 1 min read

cloneDeep 深克隆实现

algo-clonedeep

2017-09-07 · 1 min read

webpack

engin-webpack

2017-09-07 · 1 min read

http1.1和http2.0有什么区别

http1.1和http2.0有什么区别

2017-06-14 · 1 min read

手写EventEmitter事件巴士

咱们来手写实现一个EventEmitter事件巴士

2017-01-10 · 1 min read

OOP 面向对象编程

对象是什么?为什么要面向对象?

2016-05-08 · 1 min read
Stay hungry & Stay foolish
战歌
16
The Reluctant Warrior
Immediate Music
To Glory
Two Steps From Hell
Victory
Two Steps From Hell
Empire of Angels
Thomas Bergersen
Serenata Immortale
Immediate Music
Cornfield Chase
Hans Zimmer
Tennessee
Hans Zimmer
He's a Pirate
Martin Ermen
Rise
Hans Zimmer
On Thin Ice
Hans Zimmer
Angels Will Rise
Twisted Jukebo
When It All Falls Down
Audiomachine
Icarus
Ivan Torrent
Star Sky - Instrumental
Two Steps From Hell
亡灵序曲
L
Up Is Down
Hans Zimm
回到首页

跨域方法

袁官东
September 24th, 2021 · 1 min read
图:Mako Tsereteli

1、JSONP

原理

利用script标签没有跨域限制的漏洞,网页可以得到从其他来源动态产生的 JSON 数据。JSONP 请求一定需要对方的服务器做支持才可以

优缺点

JSONP 优点是简单兼容性好,可用于解决主流浏览器的跨域数据访问的问题。缺点是仅支持 get 方法具有局限性,不安全可能会遭受 XSS 攻击

实现

  • 声明一个回调函数,其函数名(如 show)当做参数值,要传递给跨域请求数据的服务器,函数形参为要获取目标数据(服务器返回的 data)。
  • 创建一个script标签,把那个跨域的 API 数据接口地址,赋值给 script 的 src,还要在这个地址中向服务器传递该函数名(可以通过问号传参:?callback=show)。
  • 服务器接收到请求后,需要进行特殊的处理:把传递进来的函数名和它需要给你的数据拼接成一个字符串,例如:传递进去的函数名是 show,它准备好的数据是 show(‘我不爱你’)。
  • 最后服务器把准备的数据通过 HTTP 协议返回给客户端,客户端再调用执行之前声明的回调函数(show),对返回的数据进行操作。
1// index.html
2function jsonp({ url, params, callback }) {
3 return new Promise((resolve, reject) => {
4 let script = document.createElement("script");
5 window[callback] = function (data) {
6 resolve(data);
7 document.body.removeChild(script);
8 };
9 params = { ...params, callback }; // wd=b&callback=show
10 let arrs = [];
11 for (let key in params) {
12 arrs.push(`${key}=${params[key]}`);
13 }
14 script.src = `${url}?${arrs.join("&")}`;
15 document.body.appendChild(script);
16 });
17}
18jsonp({
19 url: "http://localhost:3000/say",
20 params: { wd: "Iloveyou" },
21 callback: "show",
22}).then((data) => {
23 console.log(data);
24});

上面这段代码相当于向 http://localhost:3000/say?wd=Iloveyou&callback=show 这个地址请求数据,然后后台返回 show(‘我不爱你’),最后会运行 show()这个函数,打印出’我不爱你’

1// server.js
2let express = require("express");
3let app = express();
4app.get("/say", function (req, res) {
5 let { wd, callback } = req.query;
6 console.log(wd); // Iloveyou
7 console.log(callback); // show
8 res.end(`${callback}('我不爱你')`);
9});
10app.listen(3000);

2、Cors

CORS 需要浏览器和后端同时支持。IE 8 和 9 需要通过 XDomainRequest 来实现。

浏览器会自动进行 CORS 通信,实现 CORS 通信的关键是后端。只要后端实现了 CORS,就实现了跨域。

服务端设置 Access-Control-Allow-Origin 就可以开启 CORS。 该属性表示哪些域名可以访问资源,如果设置通配符则表示所有网站都可以访问资源。

虽然设置 CORS 和前端没什么关系,但是通过这种方式解决跨域问题的话,会在发送请求时出现两种情况,分别为简单请求和复杂请求。

简单请求

只要同时满足以下两大条件,就属于简单请求

  • 条件 1:使用下列方法之一:

GET

HEAD

POST

  • 条件 2:Content-Type 的值仅限于下列三者之一:

text/plain

multipart/form-data

application/x-www-form-urlencoded

请求中的任意 XMLHttpRequestUpload 对象均没有注册任何事件监听器; XMLHttpRequestUpload 对象可以使用 XMLHttpRequest.upload 属性访问。

复杂请求

不符合以上条件的请求就肯定是复杂请求了。 复杂请求的 CORS 请求,会在正式通信之前,增加一次 HTTP 查询请求,称为”预检”请求,该请求是 option 方法的,通过该请求来知道服务端是否允许跨域请求。

我们用 PUT 向后台请求时,属于复杂请求,后台需做如下配置:

1// 允许哪个方法访问我
2res.setHeader("Access-Control-Allow-Methods", "PUT");
3// 预检的存活时间
4res.setHeader("Access-Control-Max-Age", 6);
5// OPTIONS请求不做任何处理
6if (req.method === "OPTIONS") {
7 res.end();
8}
9// 定义后台返回的内容
10app.put("/getData", function (req, res) {
11 console.log(req.headers);
12 res.end("我不爱你");
13});

3、postMessage

postMessage 是 HTML5 XMLHttpRequest Level 2 中的 API,且是为数不多可以跨域操作的 window 属性之一,它可用于解决以下方面的问题:

  • 页面和其打开的新窗口的数据传递
  • 多窗口之间消息传递
  • 页面与嵌套的 iframe 消息传递
  • 上面三个场景的跨域数据传递

postMessage()方法允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递。

otherWindow.postMessage(message, targetOrigin, [transfer]);

message: 将要发送到其他 window 的数据。 targetOrigin:通过窗口的 origin 属性来指定哪些窗口能接收到消息事件,其值可以是字符串”*“(表示无限制)或者一个 URI。在发送消息的时候,如果目标窗口的协议、主机地址或端口这三者的任意一项不匹配 targetOrigin 提供的值,那么消息就不会被发送;只有三者完全匹配,消息才会被发送。 transfer(可选):是一串和 message 同时传递的 Transferable 对象. 这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权。

接下来我们看个例子: http://localhost:3000/a.html 页面向 http://localhost:4000/b.html 传递“我爱你”,然后后者传回”我不爱你”。

1// a.html
2<iframe src="http://localhost:4000/b.html" frameborder="0" id="frame" onload="load()"></iframe> //等它加载完触发一个事件
3//内嵌在http://localhost:3000/a.html
4<script>
5 function load() {
6 let frame = document.getElementById('frame')
7 frame.contentWindow.postMessage('我爱你', 'http://localhost:4000') //发送数据
8 window.onmessage = function(e) { //接受返回数据
9 console.log(e.data) //我不爱你
10 }
11 }
12</script>
1// b.html
2 window.onmessage = function(e) {
3 console.log(e.data) //我爱你
4 e.source.postMessage('我不爱你', e.origin)
5 }

4、websocket

Websocket是HTML5的一个持久化的协议,它实现了浏览器与服务器的全双工通信,同时也是跨域的一种解决方案。WebSocket和HTTP都是应用层协议,都基于 TCP 协议。但是 WebSocket 是一种双向通信协议,在建立连接之后,WebSocket 的 server 与 client 都能主动向对方发送或接收数据。同时,WebSocket 在建立连接时需要借助 HTTP 协议,连接建立好了之后 client 与 server 之间的双向通信就与 HTTP 无关了。

原生WebSocket API使用起来不太方便,我们使用Socket.io,它很好地封装了webSocket接口,提供了更简单、灵活的接口,也对不支持webSocket的浏览器提供了向下兼容。

我们先来看个例子:本地文件socket.html向localhost:3000发生数据和接受数据

1// socket.html
2<script>
3 let socket = new WebSocket('ws://localhost:3000');
4 socket.onopen = function () {
5 socket.send('我爱你');//向服务器发送数据
6 }
7 socket.onmessage = function (e) {
8 console.log(e.data);//接收服务器返回的数据
9 }
10</script>
1// server.js
2let express = require('express');
3let app = express();
4let WebSocket = require('ws');//记得安装ws
5let wss = new WebSocket.Server({port:3000});
6wss.on('connection',function(ws) {
7 ws.on('message', function (data) {
8 console.log(data);
9 ws.send('我不爱你')
10 });
11})

5、Node中间件代理(两次跨域)

实现原理:同源策略是浏览器需要遵循的标准,而如果是服务器向服务器请求就无需遵循同源策略。 代理服务器,需要做以下几个步骤:

  • 接受客户端请求 。
  • 将请求 转发给服务器。
  • 拿到服务器 响应 数据。
  • 将 响应 转发给客户端。

我们先来看个例子:本地文件index.html文件,通过代理服务器http://localhost:3000向目标服务器http://localhost:4000请求数据。

1// index.html(http://127.0.0.1:5500)
2<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
3<script>
4 $.ajax({
5 url: 'http://localhost:3000',
6 type: 'post',
7 data: { name: 'xiamen', password: '123456' },
8 contentType: 'application/json;charset=utf-8',
9 success: function(result) {
10 console.log(result) // {"title":"fontend","password":"123456"}
11 },
12 error: function(msg) {
13 console.log(msg)
14 }
15 })
16</script>
1// server1.js 代理服务器(http://localhost:3000)
2const http = require('http')
3// 第一步:接受客户端请求
4const server = http.createServer((request, response) => {
5 // 代理服务器,直接和浏览器直接交互,需要设置CORS 的首部字段
6 response.writeHead(200, {
7 'Access-Control-Allow-Origin': '*',
8 'Access-Control-Allow-Methods': '*',
9 'Access-Control-Allow-Headers': 'Content-Type'
10 })
11 // 第二步:将请求转发给服务器
12 const proxyRequest = http
13 .request(
14 {
15 host: '127.0.0.1',
16 port: 4000,
17 url: '/',
18 method: request.method,
19 headers: request.headers
20 },
21 serverResponse => {
22 // 第三步:收到服务器的响应
23 var body = ''
24 serverResponse.on('data', chunk => {
25 body += chunk
26 })
27 serverResponse.on('end', () => {
28 console.log('The data is ' + body)
29 // 第四步:将响应结果转发给浏览器
30 response.end(body)
31 })
32 }
33 )
34 .end()
35})
36server.listen(3000, () => {
37 console.log('The proxyServer is running at http://localhost:3000')
38})
1// server2.js(http://localhost:4000)
2const http = require('http')
3const data = { title: 'fontend', password: '123456' }
4const server = http.createServer((request, response) => {
5 if (request.url === '/') {
6 response.end(JSON.stringify(data))
7 }
8})
9server.listen(4000, () => {
10 console.log('The server is running at http://localhost:4000')
11})

上述代码经过两次跨域,值得注意的是浏览器向代理服务器发送请求,也遵循同源策略,最后在index.html文件打印出{“title”:“fontend”,“password”:“123456”}

6、nginx反向代理

实现原理类似于Node中间件代理,需要你搭建一个中转nginx服务器,用于转发请求。

使用nginx反向代理实现跨域,是最简单的跨域方式。只需要修改nginx的配置即可解决跨域问题,支持所有浏览器,支持session,不需要修改任何代码,并且不会影响服务器性能。

实现思路:通过nginx配置一个代理服务器(域名与domain1相同,端口不同)做跳板机,反向代理访问domain2接口,并且可以顺便修改cookie中domain信息,方便当前域cookie写入,实现跨域登录。

先下载nginx,然后将nginx目录下的nginx.conf修改如下:

1// proxy服务器
2server {
3 listen 81;
4 server_name www.domain1.com;
5 location / {
6 proxy_pass http://www.domain2.com:8080; #反向代理
7 proxy_cookie_domain www.domain2.com www.domain1.com; #修改cookie里域名
8 index index.html index.htm;
9
10 # 当用webpack-dev-server等中间件代理接口访问nignx时,此时无浏览器参与,故没有同源限制,下面的跨域配置可不启用
11 add_header Access-Control-Allow-Origin http://www.domain1.com; #当前端只跨域不带cookie时,可为*
12 add_header Access-Control-Allow-Credentials true;
13 }
14}

最后通过命令行nginx -s reload启动nginx

1// index.html
2var xhr = new XMLHttpRequest();
3// 前端开关:浏览器是否读写cookie
4xhr.withCredentials = true;
5// 访问nginx中的代理服务器
6xhr.open('get', 'http://www.domain1.com:81/?user=admin', true);
7xhr.send();
1// server.js
2var http = require('http');
3var server = http.createServer();
4var qs = require('querystring');
5server.on('request', function(req, res) {
6 var params = qs.parse(req.url.substring(2));
7 // 向前台写cookie
8 res.writeHead(200, {
9 'Set-Cookie': 'l=a123456;Path=/;Domain=www.domain2.com;HttpOnly' // HttpOnly:脚本无法读取
10 });
11 res.write(JSON.stringify(params));
12 res.end();
13});
14server.listen('8080');
15console.log('Server is running at port 8080...');

7、window.name + iframe

window.name属性的独特之处:name值在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name 值(2MB)。

其中a.html和b.html是同域的,都是http://localhost:3000;而c.html是http://localhost:4000

1// a.html(http://localhost:3000/b.html)
2 <iframe src="http://localhost:4000/c.html" frameborder="0" onload="load()" id="iframe"></iframe>
3 <script>
4 let first = true
5 // onload事件会触发2次,第1次加载跨域页,并留存数据于window.name
6 function load() {
7 if(first){
8 // 第1次onload(跨域页)成功后,切换到同域代理页面
9 let iframe = document.getElementById('iframe');
10 iframe.src = 'http://localhost:3000/b.html';
11 first = false;
12 }else{
13 // 第2次onload(同域b.html页)成功后,读取同域window.name中数据
14 console.log(iframe.contentWindow.name);
15 }
16 }
17 </script>

b.html为中间代理页,与a.html同域,内容为空。

1// c.html(http://localhost:4000/c.html)
2 <script>
3 window.name = '我不爱你'
4 </script>

8、location.hash + iframe

实现原理: a.html欲与c.html跨域相互通信,通过中间页b.html来实现。 三个页面,不同域之间利用iframe的location.hash传值,相同域之间直接js访问来通信。

具体实现步骤:一开始a.html给c.html传一个hash值,然后c.html收到hash值后,再把hash值传递给b.html,最后b.html将结果放到a.html的hash值中。 同样的,a.html和b.html是同域的,都是http://localhost:3000;而c.html是http://localhost:4000

1// a.html
2 <iframe src="http://localhost:4000/c.html#iloveyou"></iframe>
3 <script>
4 window.onhashchange = function () { //检测hash的变化
5 console.log(location.hash);
6 }
7 </script>
1// b.html
2 <script>
3 window.parent.parent.location.hash = location.hash
4 //b.html将结果放到a.html的hash值中,b.html可通过parent.parent访问a.html页面
5 </script>
1// c.html
2 console.log(location.hash);
3 let iframe = document.createElement('iframe');
4 iframe.src = 'http://localhost:3000/b.html#idontloveyou';
5 document.body.appendChild(iframe);

9、document.domain + iframe

该方式只能用于一级域名相同的情况下,比如 a.test.com 和 b.test.com 适用于该方式。 只需要给页面添加 document.domain =‘test.com’ 表示二级域名都相同就可以实现跨域。

实现原理:两个页面都通过js强制设置document.domain为基础主域,就实现了同域。

我们看个例子:页面a.zf1.cn:3000/a.html获取页面b.zf1.cn:3000/b.html中a的值

1// a.html
2<body>
3 helloa
4 <iframe src="http://b.zf1.cn:3000/b.html" frameborder="0" onload="load()" id="frame"></iframe>
5 <script>
6 document.domain = 'zf1.cn'
7 function load() {
8 console.log(frame.contentWindow.a);
9 }
10 </script>
11</body>
1// b.html
2<body>
3 hellob
4 <script>
5 document.domain = 'zf1.cn'
6 var a = 100;
7 </script>
8</body>

总结

JSONP,CORS,postMessage,websocket,node proxy,nginx,iframe[document.domain\window.name\location.hash]

CORS支持所有类型的HTTP请求,是跨域HTTP请求的根本解决方案 JSONP只支持GET请求,JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。 不管是Node中间件代理还是nginx反向代理,主要是通过同源策略对服务器不加限制。 日常工作中,用得比较多的跨域方案是cors和nginx反向代理

转载自:https://segmentfault.com/a/1190000018017118

More articles from Favori 重剑

react virtualList 虚拟列表无限滚动实现

用react实现虚拟滚动

September 16th, 2021 · 1 min read

监控埋点方案

前端监控埋点方案

September 16th, 2021 · 1 min read
© 2016–2023 Favori 重剑
Link to $https://github.com/yuanguandongLink to $https://favori.zcool.com.cn/Link to $https://codepen.io/favori