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

跨域的解决方案

一、概念

1. 浏览器的同源策略

浏览器为确保资源的安全,而遵循的一种策略。

2. 源

源 = 协议 + 域名 + 端口

3. 同源和非同源

当两个源只有他们的协议、域名、端口都一致,才是同源,否则是非同源。

4. 同源请求和非同源请求

如果是同源发出的请求就是同源请求,如果是非同源发出的请求就是非同源请求。

5. 跨域

[所处源] 与 [目标源] 不一致,就会导致跨域。

二、浏览器会对跨域做哪些限制

[源 A] 和 [源 B]是非同源的,则浏览器会有以下限制。

1. DOM 访问限制

[源 A]的脚本不能读取和操作[源 B]的 DOM

2. Cookie 访问限制

[源 A]不能访问[源 B]的 Cookie

3. Ajax 响应数据限制

[源 A]可以给[源 B]发请求,但无法获取[源 B]的返回的数据

三、注意点

跨域限制仅存在浏览器端,服务端不存在跨域限制

即时跨域了,Ajax 请求也可以正常发出,但响应数据不会交给开发者。

<link>、<script>、<img>...这些标签发出的请求也可能跨域,只不过浏览器对标签不做严格限制,对开发几乎无影响。

四、CORS 解决跨域

CORS 即跨源资源共享(Cross-Origin Resource Sharing),CORS 是一种机制,它允许 Web 应用服务器进行跨域访问控制,使不同源的网站之间能够安全地共享资源。

在默认情况下,出于安全考虑,浏览器会限制从一个源(协议、域名、端口)加载的脚本获取或操作另一个源的资源。而 CORS 为 Web 应用提供了一种安全的方式来绕过这种同源策略的限制。

使用 CORS 解决跨域是最正统的方式,且要求服务器是"自己人"

1. 简单请求和复杂请求

简单请求

请求方式:GET、HEAD、POST

Content-type:text/plain、multipart/form-data、application/x-www-form-urlencoded

请求头字段符合《CORS 安全规范》,只要你改了请求头就变复杂请求了。

复杂请求

不是简单请求就是复杂请求,复杂请求会自动发送预检请求。

2. 解决简单请求

以 nodeJS 为例,服务器端设置响应头 Access-Control-Allow-Origin,值为发送请求的源表示,只要从这个源发送的请求,都通过。值为 "\*" 表示所有不同源发来的请求都通过。

app.get("/xxx", (res, req) => {res.setHeader("Access-Control-Allow-Origin", "发送请求源" | "*");res.send();});

3. 解决复杂请求

以 nodeJS 为例,服务器设置响应头,与请求头一一对应,使用 cors 插件。

app.use(cors({origin: "xxx", // 允许源methods: ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS"], // 允许方法allowedHeaders: ["xxx"], // 允许的自定义头exposedHeaders: ["xxx"], // 要暴露的响应头}));app.get("/xxx", (res, req) => {res.setHeader("xxx", "xxx");res.send();});

五、JSONP 解决跨域

JSONP 利用<script>标签可以跨域加载脚本,且不受严格模式限制的特性。

1. 基本流程

第一步:创建 script 标签,将 src 设置为跨域请求的 url。同时准备一个回调函数,这个函数处理返回来的数据。

第二步:服务端接受到请求后,将数据封装在回调函数中返回

第三步:客户端回调函数被调用,数据以参数的形式传入回调函数

2. 例子

服务端代码

let list = [1, 2, 3];app.get("/table", (req, res) => {const { callback } = req.query;res.send(`${callback}(${JSON.stringify(list)})`);});

客户端代码

function test(data) {console.log(data);}function getTable() {const script = document.createElement("script");script.onload = () => {script.remove();};script.src = "http://xxx.xx.xx:8080/table?callback=test";document.body.appendChild(script);}

六、配置代理解决跨域

1. 自己配置代理服务器

借助 http-proxy-middleware 配置代理

const { createProxyMiddleware } = require("http-proxy-middleware");app.use("/api",createProxyMiddleware({target: "https://www.baidu.com",changeOrigin: true,pathRewrite: {"^/api": "",},}));

2. 使用 Nginx 搭建代理服务器

2.1 设置响应头

server {listen 80;server_name your_domain.com;location /api/ {add_header 'Access-Control-Allow-Origin' '*';add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';if ($request_method = 'OPTIONS') {return 204;}proxy_pass http://your_backend_server;}}

2.2 反向代理

通过 Nginx 将跨域请求代理到目标服务器,让浏览器认为是同源请求。

server {listen 80;server_name frontend.com;location /api/ {proxy_pass http://backend.com;}}

3. 脚手架服务器

比如 vue3 里的配置文件 vite.config.js 可以配置代理的地址

import { defineConfig } from "vite";// https://vitejs.dev/config/
export default defineConfig(() => {return {server: {host: "127.0.0.1",port: 8081,strictPort: false,open: true,proxy: {"/dev-api": {target: "http://localhost:1112",changeOrigin: true,rewrite: (path) => path.replace(/^\/dev-api/, ""),},},},};
});

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • SpringBoot集成MQTT实现交互服务通信
  • python 迭代器介绍 map() 函数
  • stm32入门-----EXTI外部中断(上 ——理论篇)
  • TDesign组件库日常应用的一些注意事项
  • 【Datawhale AI 夏令营2024--CV】深度学习入门
  • 泛微e-cology WorkflowServiceXml SQL注入漏洞(POC)
  • 基于嵌入式Linux的高性能车载娱乐系统设计与实现 —— 融合Qt、FFmpeg和CAN总线技术
  • 高职院校人工智能人才培养成果导向系统构建、实施要点与评量方法
  • Elasticsearch 角色和权限管理
  • 3.RabbitMQ安装-Centos7
  • 好用的AI搜索引擎
  • RISC-V在线反汇编工具
  • STM32 IAP 需要关注的一些事
  • 捷配总结的SMT工厂安全防静电规则
  • CSS3实现提示工具的渐入渐出效果及CSS3动画简介
  • 【笔记】你不知道的JS读书笔记——Promise
  • mysql中InnoDB引擎中页的概念
  • node.js
  • python docx文档转html页面
  • SpiderData 2019年2月23日 DApp数据排行榜
  • Vue 动态创建 component
  • Vue2 SSR 的优化之旅
  • 阿里云容器服务区块链解决方案全新升级 支持Hyperledger Fabric v1.1
  • 第2章 网络文档
  • 给新手的新浪微博 SDK 集成教程【一】
  • 力扣(LeetCode)56
  • 使用common-codec进行md5加密
  • 译自由幺半群
  • 远离DoS攻击 Windows Server 2016发布DNS政策
  • ​LeetCode解法汇总2670. 找出不同元素数目差数组
  • ​LeetCode解法汇总518. 零钱兑换 II
  • ‌分布式计算技术与复杂算法优化:‌现代数据处理的基石
  • $refs 、$nextTic、动态组件、name的使用
  • (2024最新)CentOS 7上在线安装MySQL 5.7|喂饭级教程
  • (4)(4.6) Triducer
  • (4)事件处理——(6)给.ready()回调函数传递一个参数(Passing an argument to the .ready() callback)...
  • (DenseNet)Densely Connected Convolutional Networks--Gao Huang
  • (pycharm)安装python库函数Matplotlib步骤
  • (安全基本功)磁盘MBR,分区表,活动分区,引导扇区。。。详解与区别
  • (第30天)二叉树阶段总结
  • (附源码)ssm基于微信小程序的疫苗管理系统 毕业设计 092354
  • (附源码)ssm教师工作量核算统计系统 毕业设计 162307
  • (附源码)ssm考试题库管理系统 毕业设计 069043
  • (附源码)计算机毕业设计SSM基于java的云顶博客系统
  • (十七)Flink 容错机制
  • (一)为什么要选择C++
  • (译)计算距离、方位和更多经纬度之间的点
  • (原創) 人會胖會瘦,都是自我要求的結果 (日記)
  • (原創) 是否该学PetShop将Model和BLL分开? (.NET) (N-Tier) (PetShop) (OO)
  • (转)Android学习系列(31)--App自动化之使用Ant编译项目多渠道打包
  • (转)AS3正则:元子符,元序列,标志,数量表达符
  • ... fatal error LINK1120:1个无法解析的外部命令 的解决办法
  • .NET CLR Hosting 简介
  • .net on S60 ---- Net60 1.1发布 支持VS2008以及新的特性
  • .net Signalr 使用笔记