当前位置: 首页 > news >正文

前端开发攻略---彻底弄懂跨域解决方案

目录

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,它们是非同源,则浏览器会有如下限制

  1. DOM访问限制:源A的脚本不能读取和操作源B的DOM
  2. Cookie访问限制:源A不能访问源B的cookie
  3. Ajax响应数据限制:源A可以给源B发请求,但是无法获取源B的响应的数据

备注:在上述限制中,浏览器对Ajax获取数据的限制是影响最大的一个,且实际开发中经常遇到

3、注意点

  1. 跨域限制仅存在浏览器端,服务端不存在跨域限制
  2. 即使跨域了,Ajax请求也可以正常发出,但响应数据不会交给开发者
  3. <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
  1. 不是简单请求,就是复杂请求
  2. 复杂请求会自动发送预检请求

请求字段要符合《CORS安全规范》

简记:只要不手动修改请求头,一般都能符合改规范

请求头的Content-Type的值只能是以下三种

  • text/plain
  • multipart/form-data
  • application/x-www-form-urlencoded

关于预检请求:

  1. 发送时机:预检请求再实际跨域请求之前发出,是由浏览器自动发起的
  2. 主要作用:用于向服务器确认是否允许接下来的跨域请求
  3. 基本流程:先发起OPTIONS请求,如果通过预检,继续发起实际的跨域请求
  4. 请求头内容:一个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 版本可能有所不同。

基本的代理配置示例如下:

  1. 打开配置文件:
    sudo nano /etc/nginx/nginx.conf
    
  2. 添加一个 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 头信息。

  3. 保存文件并退出编辑器。
  4. 测试配置是否正确:
    sudo nginx -t
    
  5. 重新加载 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是以扩张速度最快而闻名的咖啡连锁店。如果你在街角看到它的店&#xff0c;在对面街上肯定还会看到另一家。因为扩张速度实在太快了&#xff0c;他们准备更新订单系统&#xff0c;以合乎他们的饮料供应要求。他们原先的类设计是这样的…… 购买咖啡时&am…...

大白话解释TCP的三次握手和四次挥手

你好&#xff0c;我是沐爸&#xff0c;欢迎点赞、收藏和关注。个人知乎 TCP的三次握手是浏览器与服务器建立连接的过程&#xff0c;而四次挥手&#xff0c;是两者断开连接的过程。今天把客户端和服务端当做两个人&#xff0c;通过打电话的方式解释连接建立和断开的过程。 TCP…...

asyncua模块实现OPC UA通讯

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

RabbitMQ的核心概念

RabbitMQ是一个消息中间件&#xff0c;也是一个生产者消费者模型&#xff0c;负责接收&#xff0c;存储和转发消息。 核心概念 Producer 生产者&#xff0c;是RabbitMQ Server的客户端&#xff0c;向RabbitMQ发送消息。 Consumer 消费者&#xff0c;是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 关键字用于声明一个全局变量或对象&#xff0c;而不定义它。这意味着 _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): 游戏逻辑

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

嵌入式系统实时任务调度算法优化与实现

嵌入式系统实时任务调度算法优化与实现 目录 嵌入式系统实时任务调度算法优化与实现 引言 1.1 嵌入式系统的重要性 1.2 实时任务调度的重要性 实时任务的定义与分类 2.1 实时任务的定义 2.2 实时任务的分类 2.3 实时任务的其他分类方法 硬实时与软实时系统 3.1 硬实…...

Java:枚举转换

在Java中&#xff0c;你可以使用Enum.valueOf()方法将字符串转换为枚举常量。但是&#xff0c;如果你想要将枚举转换为其他类型&#xff0c;你需要自定义转换方法。以下是一个简单的例子&#xff0c;演示如何将枚举转换为整数&#xff1a; public enum Color {RED(1), GREEN(2…...

Vue、react父子组件生命周期

Vue 的父子组件生命周期 以下分为三部分&#xff0c;加载渲染阶段——更新阶段——销毁阶段&#xff0c;我们来一一介绍&#xff1a; 1、加载渲染阶段 在加载渲染阶段&#xff0c;一定得等子组件挂载完毕后&#xff0c;父组件才能挂载完毕&#xff0c;所以父组件的 mounted 在…...

HTML 基础要素解析

目录 HTML 初步认识 纯文本文件介绍 纯文本文件与其它文件的区别 Html介绍 HTML 骨架 文档类型&#xff08;!DOCTYPE&#xff09;声明 介绍 常用的 DOCTYPE 声明 meta标签 字符集 关键字和页面描述 HTML 初步认识 纯文本文件介绍 纯文本文件指的是仅包含文本内容&am…...

开源的向量数据库Milvus

Milvus是一款开源的向量数据库&#xff0c;专为处理向量搜索任务而设计&#xff0c;尤其擅长处理大规模向量数据的相似度检索。 官网地址&#xff1a;https://milvus.io/ 以下是关于Milvus的详细介绍&#xff1a; 一、基本概念 向量数据库&#xff1a;Milvus是一款云原生向量…...

设计模式-工厂方法

“对象创建”模式 通过“对象创建”模式绕开new&#xff0c;来避免对象创建&#xff08;new&#xff09;过程中所导致的紧耦合&#xff08;依赖具体类&#xff09;&#xff0c;从而支持对象创建的稳定。它是接口抽象之后的第一步工作。典型模式 Factory MethodAbstract Factory…...

Flask SQLALchemy 的使用

Flask SQLALchemy 的使用 安装 Flask-SQLAlchemy配置 Flask-SQLAlchemy定义模型创建数据库和表插入和查询数据更新和删除数据迁移数据库总结Flask-SQLAlchemy 是一个 Flask 扩展,它简化了 Flask 应用中 SQLAlchemy 的使用。SQLAlchemy 是一个强大的 SQL 工具包和对象关系映射(…...

Metasploit漏洞利用系列(一):MSF完美升级及目录结构深度解读

在信息安全领域&#xff0c;MetasploitFramework&#xff08;MSF&#xff09;是一个无处不在的工具&#xff0c;它集合了大量的渗透测试和漏洞利用模块&#xff0c;帮助安全专家识别和利用系统中的弱点。本文将深入探讨如何对Metasploit进行完美升级&#xff0c;以及对其核心目…...

C/C++|经典代码题(动态资源的双重释放与「按值传递、按引用传递、智能指针的使用」)

以下代码中你能看出其存在什么问题&#xff1f;如何修复&#xff0c;能给出几种方法&#xff1f;分别在什么场景下用哪种方法。 #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.目录操作&#xff1a; ls&#xff1a;列出目录内容。cd&#xff1a;改变当前工作目录。pwd&#xff1a;显示当前工作目录的路径。mkdir&#xff1a;创建新目录。rmd…...

Kubectl基础命令使用

一.Kubectl 基础命令 格式&#xff1a; kubectl [command] [TYPE] [NAME] [FLAGS] kubectl 是 Kubernetes 的命令行工具&#xff0c;用于管理 Kubernetes 集群。以下是一些常用的 kubectl 命令及其选项&#xff1a; 常用命令 获取资源 列出所有资源类型&#xff08;Pods、De…...

stm32G473的flash模式是单bank还是双bank?

今天突然有人stm32G473的flash模式是单bank还是双bank&#xff1f;由于时间太久&#xff0c;我真忘记了。搜搜发现&#xff0c;还真有人和我一样。见下面的链接&#xff1a;https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...

反向工程与模型迁移:打造未来商品详情API的可持续创新体系

在电商行业蓬勃发展的当下&#xff0c;商品详情API作为连接电商平台与开发者、商家及用户的关键纽带&#xff0c;其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息&#xff08;如名称、价格、库存等&#xff09;的获取与展示&#xff0c;已难以满足市场对个性化、智能…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

10-Oracle 23 ai Vector Search 概述和参数

一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI&#xff0c;使用客户端或是内部自己搭建集成大模型的终端&#xff0c;加速与大型语言模型&#xff08;LLM&#xff09;的结合&#xff0c;同时使用检索增强生成&#xff08;Retrieval Augmented Generation &#…...

LeetCode - 199. 二叉树的右视图

题目 199. 二叉树的右视图 - 力扣&#xff08;LeetCode&#xff09; 思路 右视图是指从树的右侧看&#xff0c;对于每一层&#xff0c;只能看到该层最右边的节点。实现思路是&#xff1a; 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...

【Go语言基础【12】】指针:声明、取地址、解引用

文章目录 零、概述&#xff1a;指针 vs. 引用&#xff08;类比其他语言&#xff09;一、指针基础概念二、指针声明与初始化三、指针操作符1. &&#xff1a;取地址&#xff08;拿到内存地址&#xff09;2. *&#xff1a;解引用&#xff08;拿到值&#xff09; 四、空指针&am…...

智能职业发展系统:AI驱动的职业规划平台技术解析

智能职业发展系统&#xff1a;AI驱动的职业规划平台技术解析 引言&#xff1a;数字时代的职业革命 在当今瞬息万变的就业市场中&#xff0c;传统的职业规划方法已无法满足个人和企业的需求。据统计&#xff0c;全球每年有超过2亿人面临职业转型困境&#xff0c;而企业也因此遭…...

基于江科大stm32屏幕驱动,实现OLED多级菜单(动画效果),结构体链表实现(独创源码)

引言 在嵌入式系统中&#xff0c;用户界面的设计往往直接影响到用户体验。本文将以STM32微控制器和OLED显示屏为例&#xff0c;介绍如何实现一个多级菜单系统。该系统支持用户通过按键导航菜单&#xff0c;执行相应操作&#xff0c;并提供平滑的滚动动画效果。 本文设计了一个…...

在Zenodo下载文件 用到googlecolab googledrive

方法&#xff1a;Figshare/Zenodo上的数据/文件下载不下来&#xff1f;尝试利用Google Colab &#xff1a;https://zhuanlan.zhihu.com/p/1898503078782674027 参考&#xff1a; 通过Colab&谷歌云下载Figshare数据&#xff0c;超级实用&#xff01;&#xff01;&#xff0…...

Linux操作系统共享Windows操作系统的文件

目录 一、共享文件 二、挂载 一、共享文件 点击虚拟机选项-设置 点击选项&#xff0c;设置文件夹共享为总是启用&#xff0c;点击添加&#xff0c;可添加需要共享的文件夹 查询是否共享成功 ls /mnt/hgfs 如果显示Download&#xff08;这是我共享的文件夹&#xff09;&…...