前端开发攻略---彻底弄懂跨域解决方案
目录
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 cors2、简单配置
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 nginx2、配置 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 nginx3、验证代理设置
现在,你可以通过访问你的代理服务器地址来验证是否能够成功地将请求代理到后端服务器。例如,访问
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…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...
逻辑回归:给不确定性划界的分类大师
想象你是一名医生。面对患者的检查报告(肿瘤大小、血液指标),你需要做出一个**决定性判断**:恶性还是良性?这种“非黑即白”的抉择,正是**逻辑回归(Logistic Regression)** 的战场&a…...
MongoDB学习和应用(高效的非关系型数据库)
一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...
聊聊 Pulsar:Producer 源码解析
一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台,以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中,Producer(生产者) 是连接客户端应用与消息队列的第一步。生产者…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...
C++ 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...

