前端跨域方案看这篇就够了
文章目录
- 前言
- 跨域解决的方法
- 1.JSONP
- 2.CORS跨域资源共享
- 3.http proxy => webpack webpack-dev-server
- 4.nginx反向代理
- 5.postMessage(跟Worker很像)
- 6.WebSocket协议跨域
- 总结
前言
为了加快请求响应时间,服务器进行分布式布局,将服务器分为:
web服务器:用于处理静态资源
data服务器:业务逻辑和数据分析
图片服务器
由于浏览器的同源策略,同源策略认为以下三者都一样就是同源,只要有一个不同就是跨域:
- 协议
- 域名
- 端口号
导致需要用到跨域请求。
跨域解决的方法
1.JSONP
使用不存在跨域请求的限制的html标签发送get请求,比如以下标签:
-script
-img
-link
-iframe
jsonp实现:
服务器:
let express = require('express'),app = express();app.listen(8001, () => {console.log("OK!");
})app.get('/list', (req, res) => {let { callback = Function.prototype } = req.query;let data = {code: 0,message: "珠峰培训"};res.send(`${callback}(${JSON.stringify(data)})`)
})
客户端:
<!DOCTYPE html>
<html>
<head><title>GoJSONP</title>
</head><body>
<script type="text/javascript">function jsonhandle(data){alert("age:" + data.age + "name:" + data.name);}</script><script crossorigin="anonymous" integrity="sha384-rY/jv8mMhqDabXSo+UCggqKtdmBfd3qC2/KvyTDNQ6PcUJXaxK1tMepoQda4g5vB" src="https://lib.baomitu.com/jquery/2.2.4/jquery.min.js"></script>
<script type="text/javascript">$(document).ready(function(){var url = "http://127.0.0.1:8001/list?callback=jsonhandle";var obj = $('<script><\/script>');obj.attr("src",url);$("body").append(obj);});</script>
</body>
</html>
结果:
问题:JSONP只能支持GET请求。
2.CORS跨域资源共享
做法:
1.客户端(发送ajax/fetch请求)
<!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><script src = "./node_modules/_axios@0.21.1@axios/dist/axios.js"></script><script>axios.get('http://127.0.0.1:3001/list').then(result =>{console.log(result);})</script></body></html>
2.服务器端设置相关的头信息(需要处理options试探性请求)
let express = require('express'),app = express();app.use('*', function (req, res, next) {res.header('Access-Control-Allow-Origin', '*'); //这个表示任意域名都可以访问,这样写不能携带cookie了。为了保证安全//res.header('Access-Control-Allow-Origin', 'http://www.baidu.com'); //这样写,只有www.baidu.com 可以访问。res.header('Access-Control-Allow-Credentials', true);res.header('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild');res.header('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS');//设置方法if (req.method == 'OPTIONS') {res.send(200); // 意思是,在正常的请求之前,会发送一个验证,是否可以请求。}else {next();}
});app.listen(3001, () => {console.log("OK!");
})app.get('/list', (req, res) => {let data = {code: 200,message: "我是服务器的数据!"};res.send(data)
})
3.http proxy => webpack webpack-dev-server
我们配置如下:
webpack.config.js
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');module.exports = {mode: "production",entry: './fun.js',output: { // 输出配置filename: './built.js', // 输出文件名path: resolve(__dirname, 'build/js') // 输出文件路径配置},plugins: [new HtmlWebpackPlugin({template: './please.html',filename: 'index.html'})],devServer: {port: 3000,progress: true,contentBase: './build',open: true// proxy: {// '/': {// target: 'https://www.baidu.com/',// changeOrigin: true// }// }}
}
fun.js如下:
import axios from "axios"axios.get('https://www.baidu.com/').then(res => {console.log(res);
})
打开webpack内置的服务器: npx webpack-dev-server。
会发生跨域,那么我们需要把devServer上的proxy注释去掉。就可以了。
这是Node中间件 代理实现的!
就是用Node来搭了一个代理服务器帮忙转发客户端的请求??毕竟服务器和服务器不存在跨域。
如果要发行呢??毕竟devServer 是方便我们调试。那么就需要用node来做代理了。
4.nginx反向代理
不需要前端干啥。其实就是nginx帮我们加了Access-Control-Allow-Origin的请求头啦。
5.postMessage(跟Worker很像)
我们先看看postMessage由谁来调用:
语法
otherWindow.postMessage(message, targetOrigin, [transfer]);
otherWindow
其他窗口的一个引用,比如iframe的contentWindow属性、执行window.open返回的窗口对象、或者是命名过或数值索引的window.frames。
另外一种说法是:
otherWindow
对将接收消息的窗口的引用。获得此类引用的方法包括:
Window.open
(生成一个新窗口然后引用它),Window.opener
(引用产生这个的窗口,返回打开当前窗口的那个窗口的引用,例如:在window A中打开了window B,B.opener 返回 A.),HTMLIFrameElement.contentWindow
(<iframe>
从其父窗口引用嵌入式),Window.parent
(从嵌入式内部引用父窗口<iframe>
)Window.frames
+索引值(命名或数字)。
或者看看MDN上描述:
window.postMessage MDN
otherWindow.postMessage(message, targetOrigin, [transfer])
otherWindow: A reference to another window(发送方的引用)
message:Data to be sent to the other window.(要发送到接受方的数据)
targetOrigin:Specifies what the origin of otherWindow must be for the event to be dispatched(接收方的 源,还有必须要有监听message事件)
使用:
我们先建立两个不同源的服务器:
let express = require('express'),app = express();app.use(express.static('./'));app.listen(1001, () => {console.log("port of 1001 OK!");
})
let express = require('express'),app = express();app.use(express.static('./'));app.listen(1002, () => {console.log("port of 1002 OK!");
})
1001.html,这个文件跑在域名为127.0.0.1:1001的服务器上,用于向域名为127.0.0.1:1002的服务器发送数据:
<!DOCTYPE html>
<html lan上g="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>
fuwfuq
<body><h1>server1</h1><iframe id="myframe" src="http://127.0.0.1:1002/1002.html" frameborder="0"></iframe><script>myframe.onload = function () { //注意要onload之后,才可以用postMessagelet iframeWindow = myframe.contentWindow;iframeWindow.postMessage("宁静致远", "http://127.0.0.1:1002/1002.html");}//监听B传递的信息window.onmessage = function (ev) {console.log(ev.data);}</script></body></html>
这里有个需要注意的问题,我们 发送方的引用,即调用postMessage() 那个引用的源要与接受方的源即postMessage()的第二的参数 要同源。
1002.html,这个文件跑在域名为127.0.0.1:1002的服务器上,用于向域名为127.0.0.1:1001的服务器发送和接收数据:
<!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>server2</h1><script>//监听A发送过来的信息window.onmessage = function (ev) {console.log("server2 recevice message");ev.source.postMessage("recevice message", ev.origin);}</script>
</body></html>
结果:
这种方法本质是在一个页面上通过iframe标签打开不同源的其它页面,通过主页面与iframe交流的方法postMessage进行数据的交流。可以进行get和post请求。
6.WebSocket协议跨域
总结
前端跨域方案可以分为4个方向:
- 通过没有同源策略限制的Html标签实现数据请求。
- 在客户端建一个服务器代理。
- 请求加上access-control-change- 请求头。
- 使用websocket协议。
前端跨域方案看这篇就够了相关推荐
- java fileupload上传附件到服务器,可携带参数(简单易用)可跨域,看这篇就够了
一个很简单实用的上传附件实例 首先主要用到的包: 先看服务端代码,我这里是用了Servlet,在web.xml配置 <servlet><servlet-class>com.fi ...
- 前端跨域请求get_(单点登录)跨域SSO看这篇文章就够了:前端篇
前言 前俩篇文章,我们从概念,聊到了服务器中设计的内容.不知道大家是否觉得通俗易懂呢? 接下来的内容则有些偏向前端部分. 正文 三.Cookie传递 3.1.通过URL参数实现跨域信息传递 我们要在A ...
- Spring Cloud Gateway CORS 方案看这篇就够了
欢迎关注方志朋的博客,回复"666"获面试宝典 在 SpringCloud 项目中,前后端分离目前很常见,在调试时,会遇到两种情况的跨域: 前端页面通过不同域名或IP访问微服务的后 ...
- 前端跨域问题汇总及解决方案
"关注 前端开发社区 ,回复" 1" 即可加入 前端技术交流群,回复 " 2" 即可免费领取500G前端干货! 来源 | https://seg ...
- 解决前端跨域的几种方法
解决前端跨域的几种方法 了解跨域出现的原因 解决跨域的几种方法 想要解决跨域 先要知道为什么会出现跨域 跨域:指的是浏览器不能执行其他网站的脚本 它是由浏览器的同源策略造成的 是浏览器对javascr ...
- 9种常见的前端跨域解决方案
9种常见的前端跨域解决方案(详解) 2019.09.02 21:54 73879浏览 一.什么是跨域? 在前端领域中,跨域是指浏览器允许向服务器发送跨域请求,从而克服Ajax只能同源使用的限制. ...
- 前端战五渣学前端——跨域
跨域(Cross-Origin) 这几年的工作.面试中,还遇到一个不能回避的问题,那就是跨域,一般面试的时候会问你'怎么解决跨域问题','跨域是什么','为什么会有跨域'等类似的问题.前段时间后端大佬 ...
- 聊聊前端跨域的爱恨情仇
今天是过完春节以后的第二周啦,而我好像终于回到正常工作的状态了呢,因为突然间就对工作产生了厌倦的情绪,Bug就像无底洞一样吞噬着我的脑细胞.人类就像一颗螺丝钉一样被固定在整部社会机器上,除了要让自己看 ...
- 前端跨域jsonp的细节,挡住面试官的连环提问
1.前言 在前端面试中,想必每一个人都会被问到跨域相关的问题,背过八股文的小伙伴肯定对跨域的解决对答如流,常见的跨域解决方案在网上有很多整理,但是如果问到实现的细节,你是否能够手写实现或者深入解读呢? ...
最新文章
- Linux之文档与目录结构
- CRC32算法详细推导(2)
- Spring Boot项目优雅的全局异常处理方式(全网最新)
- “抱大腿”的正确姿势
- 利用Diskgen找回分区破坏前的资料
- SQL Server触发器创建、删除、修改、查看
- xlc mysql_mysql – 用于存储产品信息的noSQL?
- 解决Conda install tensorflow弹窗Python.exe已经停止工作的问题
- 哪种修复redis未授权访问漏洞的方法是相对不安全的_redis漏洞复现
- 3S基础知识:MapX应用教程—创建地图对象
- VS2017+OpenCV4.1.0(VC15)、VS2015+OpenCV3.4.1(VC14) 配置
- 推荐的五款市面上常用的免费CMS建站系统
- Linux 服务器配置 ASF 云挂卡
- python自动输入支付密码_python接入支付宝的实例操作
- 量子计算机原理以及量子算法
- 汇编语言clr c什么意思,汇编程序中C(1):errorC129:missing';'before Bit是什么意思,加了分号也不对,怎么回事啊...
- Python爬取新冠肺炎疫情实时数据(丁香园)
- 同元车辆模型库——TA系列
- 组策略部署Office 2007
- 外卖返利小程序系统公众号外卖饿了么美团cps返利小程序分销系统