前端开发攻略---彻底弄懂跨域解决方案
目录
1、浏览器的同源策略
1.1 源
1.2 同源与非同源
1.3 同源请求与非同源请求
2、跨域受到的限制
3、注意点
4、CORS解决Ajax跨域问题
4.1 CORS概述
4.2 CORS解决简单请求跨域
4.3 简单请求与复杂请求
4.4 CORS解决复杂请求跨域
4.5 借助CORS库快速完成配置
5、JSONP解决跨域
6、配置代理解决跨域
6.1 自己配置代理服务器
6.2 使用Nginx搭建代理服务器
6.3 借助脚手架搭建代理服务器
1、浏览器的同源策略
浏览器为了确保资源安全,而遵循的一种策略。
1.1 源
源 = 协议 + 域名 + 端口号
1.2 同源与非同源
1.3 同源请求与非同源请求
所处源与目标源不一致,就是非同源,又称异源或跨域
2、跨域受到的限制
例如:源A和源B,它们是非同源,则浏览器会有如下限制
- DOM访问限制:源A的脚本不能读取和操作源B的DOM
- Cookie访问限制:源A不能访问源B的cookie
- Ajax响应数据限制:源A可以给源B发请求,但是无法获取源B的响应的数据
备注:在上述限制中,浏览器对Ajax获取数据的限制是影响最大的一个,且实际开发中经常遇到
3、注意点
- 跨域限制仅存在浏览器端,服务端不存在跨域限制
- 即使跨域了,Ajax请求也可以正常发出,但响应数据不会交给开发者
- <link>、<script>、<img>....这些标签发出的请求也可能跨域,只不过浏览器对标签跨域不做严格限制,对开发几乎无影响
4、CORS解决Ajax跨域问题
4.1 CORS概述
CORS全称:Cross-Origin Resource Sharing(跨域资源共享),是用于控制浏览器校验跨域请求的一套规范,服务器依照CORS规范,添加特定响应头来控制浏览器校验,规则如下:
- 服务器明确表示拒绝跨域请求,或没有表示,则浏览器校验不通过
- 服务器明确表示允许跨域请求,则浏览器校验通过
备注:使用CORS解决跨域是最正统的方式,且要求服务器是“自己人”
4.2 CORS解决简单请求跨域
整体思路:服务器在给出响应时,通过添加Access-Control-Allow-Origin响应头,来明确表达允许某个源发起跨域请求,随后浏览器在校验时,直接通过
服务端核心代码,以(express框架为例)
const express = require('express')const app = express()const data = [{ id: 123, name: '张三' },{ id: 456, name: '李四' },{ id: 789, name: '赵云' }, ] app.get('/student', (req, res) => {res.setHeader('Access-Control-Allow-Origin', 'http://127.0.0.1:5500')res.send(data) })app.listen(1234, () => {console.log('服务运行中...') })
4.3 简单请求与复杂请求
CORS会把请求分为两类、分别是:简单请求、复杂请求
简单请求 复杂请求 请求方法为:GET、HEAD、POST
- 不是简单请求,就是复杂请求
- 复杂请求会自动发送预检请求
请求字段要符合《CORS安全规范》
简记:只要不手动修改请求头,一般都能符合改规范
请求头的Content-Type的值只能是以下三种
- text/plain
- multipart/form-data
- application/x-www-form-urlencoded
关于预检请求:
- 发送时机:预检请求再实际跨域请求之前发出,是由浏览器自动发起的
- 主要作用:用于向服务器确认是否允许接下来的跨域请求
- 基本流程:先发起OPTIONS请求,如果通过预检,继续发起实际的跨域请求
- 请求头内容:一个OPTIONS预检请求,通常会包含如下请求头
请求头 含义 Origin 发起请求的源 Access-Control-Request-Method 实际请求的HTTP方法 Access-Control-Request-Headers 实际请求中使用的自定义头(如果有的话)
4.4 CORS解决复杂请求跨域
1、第一步:服务器先通过浏览器的预检请求,服务器需要返回如下响应头
响应头 含义 Access-Control-Allow-Origin 允许的源 Access-Control-Allow-Methods 允许的方法 Access-Control-Allow-Headers 允许的自定义头 Access-Control-Max-Age
预检请求的结果缓存时间(可选) 服务端核心代码:
const express = require('express')const app = express()const data = [{ id: 123, name: '张三' },{ id: 456, name: '李四' },{ id: 789, name: '赵云' }, ]app.options('/student', (req, res) => {res.setHeader('Access-Control-Allow-Origin', 'http://127.0.0.1:5500')res.setHeader('Access-Control-Allow-Method', 'GET')res.setHeader('Access-Control-Allow-Headers', 'a,b,c')res.setHeader('Access-Control-Allow-Age', 9000)res.send() })app.get('/student', (req, res) => {res.setHeader('Access-Control-Allow-Origin', 'http://127.0.0.1:5500')res.send(data) })app.listen(1234, () => {console.log('服务运行中...') })
4.5 借助CORS库快速完成配置
上述的配置中需要自己配置响应头,或者需要自己手动封装中间件,借助cors库,可以更方便完成配置
1、安装cors
npm i cors
2、简单配置
app.use(cors())
3、完整配置
const corsOption = {origin: 'http://127.0.0.1:5500', // 允许的源methods: ['GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS'], // 允许的方法allowedHeaders: [], // 允许的自定义头exposedHeaders: [], // 要暴露的响应头optionsSuccessStatus: 200, // 预检请求成功的状态码 } app.use(cors(corsOption))
5、JSONP解决跨域
1、JSONP概述:JSONP是利用了<script>标签可以跨域加载脚本,且不受严格限制的特性,可以说是程序员智慧的结晶,早起一些浏览器不支持CORS时,可以靠JSONP解决跨域
2、基本流程
- 第一步:客户端创建一个<script>标签,并将其src属性设置为包含跨域请求的URL,同时准备一个回调函数,这个回调函数用于处理返回的数据
- 第二步:服务端接收到请求后,将数据封装在回调函数中并返回
- 第三步:客户端的回调函数被调用。数据以参数的形式传入回调函数。
3、图示
4、服务端核心代码:
const express = require('express') const app = express()const data = [{ id: 123, name: '张三' },{ id: 456, name: '李四' },{ id: 789, name: '赵云' }, ]app.get('/getData', (req, res) => {res.send(`fn(${JSON.stringify(data)})`) })app.listen(1234, () => {console.log('服务运行中...') })
5、客户端核心代码:
<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title></head><body><button onclick="getData()">获取数据</button></body><script>function fn(data) {console.log(data)}function getData() {const script = document.createElement('script')script.onload = () => {script.remove()}script.src = 'http://127.0.0.1:1234/getData'document.body.appendChild(script)}</script> </html>
6、配置代理解决跨域
6.1 自己配置代理服务器
借助 http-proxy-middleware 配置代理
const { createProxyMiddleware } = require('http-proxy-middleware')// 拦截所有带有'/api'的请求,转发给target app.use('/api',createProxyMiddleware({target: 'https://www.toutiao.com',changOrigin: true, // 允许跨域pathRewrite: {'^/api': '',},}) )
6.2 使用Nginx搭建代理服务器
1. 安装 Nginx
首先,你需要在你的服务器上安装 Nginx。根据你的操作系统,安装步骤可能有所不同。
在 Ubuntu/Debian 系统上:
sudo apt update sudo apt install nginx
在 CentOS/RHEL 系统上:
sudo yum install epel-release sudo yum install nginx
在 Fedora 系统上:
sudo dnf install nginx
安装完成后,启动 Nginx 并设置开机自启:
sudo systemctl start nginx sudo systemctl enable nginx
2、配置 Nginx 作为代理服务器
接下来,配置 Nginx 作为代理服务器。你可以编辑 Nginx 配置文件,通常在
/etc/nginx/nginx.conf
或/etc/nginx/sites-available/default
,具体路径根据操作系统和 Nginx 版本可能有所不同。基本的代理配置示例如下:
- 打开配置文件:
sudo nano /etc/nginx/nginx.conf
- 添加一个
server
块来配置代理设置。例如,假设你想要将所有请求代理到http://backend-server
:http {...server {listen 80;server_name your-domain.com;location / {proxy_pass http://backend-server; # 后端服务器的地址proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;}}... }
这里的
proxy_pass
指令将请求转发到http://backend-server
。你可以根据需要更改为你实际的后端服务器地址。
proxy_set_header
指令用于设置转发请求时的 HTTP 头信息。- 保存文件并退出编辑器。
- 测试配置是否正确:
sudo nginx -t
- 重新加载 Nginx 配置:
sudo systemctl reload nginx
3、验证代理设置
现在,你可以通过访问你的代理服务器地址来验证是否能够成功地将请求代理到后端服务器。例如,访问
http://your-domain.com
,你应该能够看到来自http://backend-server
的内容。4、其他配置(可选)
根据需求,你可能还需要进行其他配置,例如:
- 负载均衡: 如果你有多个后端服务器,可以使用
upstream
块来进行负载均衡。- SSL/TLS 加密: 如果你需要 HTTPS,可以配置 SSL 证书来加密代理流量。
- 缓存: 配置 Nginx 缓存以提高性能。
6.3 借助脚手架搭建代理服务器
修改
vue.config.js
文件:// vue.config.js module.exports = {devServer: {proxy: 'http://localhost:5000', // 代理到你的后端服务器// 或者使用对象形式配置多个代理/*proxy: {'/api': {target: 'http://localhost:5000',changeOrigin: true,pathRewrite: { '^/api': '' },},},*/}, };
相关文章:

前端开发攻略---彻底弄懂跨域解决方案
目录 1、浏览器的同源策略 1.1 源 1.2 同源与非同源 1.3 同源请求与非同源请求 2、跨域受到的限制 3、注意点 4、CORS解决Ajax跨域问题 4.1 CORS概述 4.2 CORS解决简单请求跨域 4.3 简单请求与复杂请求 4.4 CORS解决复杂请求跨域 4.5 借助CORS库快速完成配置 5、JS…...

【HeadFirst 设计模式】装饰者模式的C++实现
一、案例背景 Starbuzz是以扩张速度最快而闻名的咖啡连锁店。如果你在街角看到它的店,在对面街上肯定还会看到另一家。因为扩张速度实在太快了,他们准备更新订单系统,以合乎他们的饮料供应要求。他们原先的类设计是这样的…… 购买咖啡时&am…...
大白话解释TCP的三次握手和四次挥手
你好,我是沐爸,欢迎点赞、收藏和关注。个人知乎 TCP的三次握手是浏览器与服务器建立连接的过程,而四次挥手,是两者断开连接的过程。今天把客户端和服务端当做两个人,通过打电话的方式解释连接建立和断开的过程。 TCP…...

asyncua模块实现OPC UA通讯
asyncua是OPCUA的python实现,使用起来非常方便,其github地址是https://github.com/FreeOpcUa/opcua-asyncio UaExpert是OPC UA Client的GUI工具,当编写好server代码后并运行,我们可以使用UaExpert去和server进行通信。UaExpert使…...

RabbitMQ的核心概念
RabbitMQ是一个消息中间件,也是一个生产者消费者模型,负责接收,存储和转发消息。 核心概念 Producer 生产者,是RabbitMQ Server的客户端,向RabbitMQ发送消息。 Consumer 消费者,是RabbitMQ Server的客…...

【vSphere 7/8】深入浅出 vSphere 证书 Ⅰ—— 初识和了解 vSphere证书
目录 摘要1. vSphere 安全证书1.1 vSphere 安全证书的类型和有效期 2. 在 vSphere Client 中初识 vSphere 证书2.1 vCenter 8.0.3 的 vSphere Client 界面2.2 vCenter Server 7.0 Update2 到 vCenter Server 8.0 Update 2 的 vSphere Client 界面2.3 vCenter Server 7.0 到 vCe…...

【云备份】服务端模块-热点管理
文章目录 0.回顾extern1.介绍2.实现思想3.代码测试代码 热点管理总结 0.回顾extern extern cloudBackup::DataManager *_dataManager extern 关键字用于声明一个全局变量或对象,而不定义它。这意味着 _dataManager 是一个指向 cloudBackup::DataManager 类型的指针…...
call apply bind特性及手动实现
call // 原生的call var foo { value: 1 };function bar(...args) {console.log("this", this.value, args); }bar.call(foo)// call 改变了bar的this指向 // bar函数执行了 // 等价于 // var foo { // name: "tengzhu", // sex: "man", …...

pygame开发课程系列(5): 游戏逻辑
第五章 游戏逻辑 在本章中,我们将探讨游戏开发中的核心逻辑,包括碰撞检测、分数系统和游戏状态管理。这些元素不仅是游戏功能的关键,还能显著提升游戏的趣味性和挑战性。 5.1 碰撞检测 碰撞检测是游戏开发中的一个重要方面,它用…...

嵌入式系统实时任务调度算法优化与实现
嵌入式系统实时任务调度算法优化与实现 目录 嵌入式系统实时任务调度算法优化与实现 引言 1.1 嵌入式系统的重要性 1.2 实时任务调度的重要性 实时任务的定义与分类 2.1 实时任务的定义 2.2 实时任务的分类 2.3 实时任务的其他分类方法 硬实时与软实时系统 3.1 硬实…...
Java:枚举转换
在Java中,你可以使用Enum.valueOf()方法将字符串转换为枚举常量。但是,如果你想要将枚举转换为其他类型,你需要自定义转换方法。以下是一个简单的例子,演示如何将枚举转换为整数: public enum Color {RED(1), GREEN(2…...
Vue、react父子组件生命周期
Vue 的父子组件生命周期 以下分为三部分,加载渲染阶段——更新阶段——销毁阶段,我们来一一介绍: 1、加载渲染阶段 在加载渲染阶段,一定得等子组件挂载完毕后,父组件才能挂载完毕,所以父组件的 mounted 在…...
HTML 基础要素解析
目录 HTML 初步认识 纯文本文件介绍 纯文本文件与其它文件的区别 Html介绍 HTML 骨架 文档类型(!DOCTYPE)声明 介绍 常用的 DOCTYPE 声明 meta标签 字符集 关键字和页面描述 HTML 初步认识 纯文本文件介绍 纯文本文件指的是仅包含文本内容&am…...

开源的向量数据库Milvus
Milvus是一款开源的向量数据库,专为处理向量搜索任务而设计,尤其擅长处理大规模向量数据的相似度检索。 官网地址:https://milvus.io/ 以下是关于Milvus的详细介绍: 一、基本概念 向量数据库:Milvus是一款云原生向量…...
设计模式-工厂方法
“对象创建”模式 通过“对象创建”模式绕开new,来避免对象创建(new)过程中所导致的紧耦合(依赖具体类),从而支持对象创建的稳定。它是接口抽象之后的第一步工作。典型模式 Factory MethodAbstract Factory…...
Flask SQLALchemy 的使用
Flask SQLALchemy 的使用 安装 Flask-SQLAlchemy配置 Flask-SQLAlchemy定义模型创建数据库和表插入和查询数据更新和删除数据迁移数据库总结Flask-SQLAlchemy 是一个 Flask 扩展,它简化了 Flask 应用中 SQLAlchemy 的使用。SQLAlchemy 是一个强大的 SQL 工具包和对象关系映射(…...
Metasploit漏洞利用系列(一):MSF完美升级及目录结构深度解读
在信息安全领域,MetasploitFramework(MSF)是一个无处不在的工具,它集合了大量的渗透测试和漏洞利用模块,帮助安全专家识别和利用系统中的弱点。本文将深入探讨如何对Metasploit进行完美升级,以及对其核心目…...
C/C++|经典代码题(动态资源的双重释放与「按值传递、按引用传递、智能指针的使用」)
以下代码中你能看出其存在什么问题?如何修复,能给出几种方法?分别在什么场景下用哪种方法。 #include <iostream>class Buffer {public:Buffer() { std::cout << "Buffer created" << std::endl; }~Buffer() { s…...
西北乱跑娃 -- linux使用笔记
1.后台运行每天一个日志文件 nohup python3.8 manage.py >> $(date %Y-%m-%d).log 2>&1 &2.目录操作: ls:列出目录内容。cd:改变当前工作目录。pwd:显示当前工作目录的路径。mkdir:创建新目录。rmd…...

Kubectl基础命令使用
一.Kubectl 基础命令 格式: kubectl [command] [TYPE] [NAME] [FLAGS] kubectl 是 Kubernetes 的命令行工具,用于管理 Kubernetes 集群。以下是一些常用的 kubectl 命令及其选项: 常用命令 获取资源 列出所有资源类型(Pods、De…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...

springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...
条件运算符
C中的三目运算符(也称条件运算符,英文:ternary operator)是一种简洁的条件选择语句,语法如下: 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true,则整个表达式的结果为“表达式1”…...

STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

CMake 从 GitHub 下载第三方库并使用
有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...
服务器--宝塔命令
一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行! sudo su - 1. CentOS 系统: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...