CORS跨域问题梳理

news/2024/11/17 12:24:08/文章来源:https://www.cnblogs.com/sherioc/p/18304328

什么是跨域

浏览器的同源策略:浏览器为确保资源安全,而遵循的一种策略,该策略对访问资源进行了一些限制
https://www.w3.org/Security/wiki/Same_Origin_Policy
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS

1、发生跨域后会出现的问题:

1、限制DOM访问
<!-- <iframe id="framePage" src="./demo.html"></iframe> -->
<iframe id="framePage" src="https://www.baidu.com"></iframe><script type="text/javascript" >function showDOM(){const framePage = document.getElementById('framePage')console.log(framePage.contentWindow.document) //同源的可以获取,非同源的无法获取}
</script>
2、限制cookie访问(实际上dom无法访问,cookie也自然无法访问了)
<iframe id="baidu" src="http://www.baidu.com" width="500" height="300"></iframe><script type="text/javascript" >// 访问的是当前源的cookie,并不是baidu的cookieconsole.log(document.cookie)
</script>
3、限制Ajax获取数据(请求可以发出,但是无法获取源B的响应数据)
const url = 'https://www.toutiao.com/hot-event/hot-board/?origin=toutiao_pc'
let result = await fetch(url)
let data = await result.json();
console.log(data)

2、注意点

1、跨域限制仅存在浏览器端,服务端不存在跨域限制
2、即使跨域了,Ajax 请求也可以正常发出,但响应数据不会交给开发者
image

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

跨域的解决方案

1、解决方案一:CORS

CORS 全称:Cross-Origin Resource Sharing(跨域资源共享),是用于控制浏览器校验跨域请求的一套规范,服务器依照 CORS 规范,添加特定响应头来控制浏览器校验,大致规则如下:
● 服务器明确表示拒绝跨域请求,或没有表示,则浏览器校验不通过。
● 服务器明确表示允许跨域请求,则浏览器校验通过

(1)处理简单请求

简单请求

  • 请求方法为:GET、HEAD、POST
  • 请求头的Content-Type的值只能是以下三种:
    ● text/plain
    ● multipart/form-data
    ● application/x-www-form-urlencoded

服务器响应时候,添加Access-Control-Allow-Origin响应头,声明允许某个源发起跨域请求,浏览器校验通过
image

服务端核心代码(以express框架为例)
// 处理跨域中间件
function corsMiddleWare(req,res,next){// 允许 http://127.0.0.1:5500 这个源发起跨域请求// res.setHeader('Access-Control-Allow-Origin','http://127.0.0.1:5500')// 允许所有源发起跨域请求res.setHeader('Access-Control-Allow-Origin','*')next()
}// 配置路由并使用中间件
app.get('/',corsMiddleWare,(req,res)=>{res.send('hello!')
})

(2)处理复杂请求

复杂请求:不是简单请求的请求就是复杂请求,比如application/json
复杂请求会自动发送预检请求

image

解决方案

第一步:服务器先通过浏览器的预检请求,服务器需要返回如下响应头:

image

第二步:处理实际的跨域请求(与处理简单请求跨域的方式相同)
image

服务端核心代码
// 处理预检请求
app.options('/students', (req, res) => {// 设置允许的跨域请求源res.setHeader('Access-Control-Allow-Origin', 'http://127.0.0.1:5500')// 设置允许的请求方法res.setHeader('Access-Control-Allow-Methods', 'GET')// 设置允许的请求头res.setHeader('Access-Control-Allow-Headers', 'school')// 设置预检请求的缓存时间(可选)res.setHeader('Access-Control-Max-Age', 7200)// 发送响应res.send()
})// 处理实际请求
app.get('/students', (req, res) => {// 设置允许的跨域请求源res.setHeader('Access-Control-Allow-Origin', 'http://127.0.0.1:5500')// 随便设置一个自定义响应头res.setHeader('abc',123)// 设置允许暴露给客户端的响应头res.setHeader('Access-Control-Expose-Headers', 'abc')// 打印请求日志console.log('有人请求/students了')// 发送响应数据res.send(students)
})

2、解决方案二:使用cors库等

nodejs
// 配置cors库
app.use(cors())
// cors中间件配置
const corsOptions = {origin: 'http://127.0.0.1:5500', // 允许的源methods: ['GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS'], // 允许的方法allowedHeaders: ['school'], // 允许的自定义头exposedHeaders: ['abc'], // 要暴露的响应头optionsSuccessStatus: 200 // 预检请求成功的状态码
};app.use(cors(corsOptions)); // 使用cors中间件
django
INSTALLED_APPS = ['django.contrib.admin',...'django.contrib.messages','django.contrib.staticfiles',# 处理跨域'corsheaders',
]MIDDLEWARE = [...'django.contrib.sessions.middleware.SessionMiddleware',# 处理跨域"corsheaders.middleware.CorsMiddleware",...
]

3、解决方案三、JSONP

  1. JSONP 概述: JSONP 是利用了<script>标签可以跨域加载脚本,且不受严格限制的特性,可以说是程序员智慧的结晶,早期一些浏览器不支持 CORS 的时,可以靠 JSONP 解决跨域。
  2. 基本流程:
    ○ 第一步:客户端创建一个<script>标签,并将其src属性设置为包含跨域请求的 URL,同时准备一个回调函数,这个回调函数用于处理返回的数据。
    ○ 第二步:服务端接收到请求后,将数据封装在回调函数中并返回。
    ○ 第三步:客户端的回调函数被调用,数据以参数的形势传入回调函数。
    image
JavaScript核心代码
<button onclick="getTeachers()">获取数据</button><script type="text/javascript" >function callback(data){console.log(data)}function getTeachers(url){// 创建script元素const script = document.createElement('script')// 指定script的src属性script.src= 'http://127.0.0.1:8081/teachers'// 将script元素添加到body中触发脚本加载document.body.appendChild(script)// script标签加载完毕后移除该标签script.onload = ()=>{script.remove()}}
</script>
jQuery 封装的 jsonp
$.getJSON('http://127.0.0.1:8081/teachers?callback=?',(data)=>{console.log(data)
})

4、配置代理解决跨域

4.1 自己配置代理服务器

借助http-proxy-middleware配置代理
const { createProxyMiddleware } = require('http-proxy-middleware');app.use('/api',createProxyMiddleware({target:'https://www.toutiao.com',changeOrigin:true,pathRewrite:{'^/api':''}
}))

4.2

基于nginx搭建代理服务器,基于Vue等脚手架搭建代理服务器(本质上是对4.1的封装)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/744386.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux/unix/windows 查询服务器查询出口 ip

1. 使用 curl 命令 比如下面这个 curl cip.cc 2. 也可以在浏览器中直接输入 url 地址:http://www.cip.cc/ 3. 其他的类似的网址: https://ipinfo.io/ curl ipinfo.iohttps://ifconfig.me/ curl ifconfig.mehttps://ifconfig.io/ curl ifconfig.iohttps://icanhazip.com/ cu…

五、Python函数之基础

全局变量与局部变量 顶头,没有任何缩进就是全局变量 函数里的变量是局部变量 如果在函数里使用 global全局变量,则可以改变全局变量。 如果没有global全局变量,调用全局变量的时候,只能读取,无法重新赋值 nonlocal 取上一级变量 书写规范 全局变量大写 局部变量小写 递归函…

STM32时钟体系、SetSysClock、PLL、时钟源

简要介绍了一、时钟体系 1、参考手册 2、时钟源3种 3、时钟树 4.时钟详解 HSE时钟 HSI时钟 锁相环时钟 系统时钟 HCLK时钟 PCLK1时钟 PCLK2时钟 RTC时钟 独立看门狗时钟: 12S时钟: 以太网PHY时钟: USBPHY时钟: MCO时钟输出 系统时钟配置函数SetsysClockO 系统时钟配置流程 …

YApi可视化接口管理平台部署

使用我们提供的 yapi-cli 工具,部署 YApi 平台是非常容易的。执行 yapi server 启动可视化部署程序,输入相应的配置和点击开始部署,就能完成整个网站的部署。部署完成之后,可按照提示信息,执行 node/{网站路径/server/app.js} 启动服务器。在浏览器打开指定url, 点击登录输…

八大作业管理流程

安全影响力的小编非常喜欢王老师的风格,抄了他的创意,把八大高危作业做了一个“一图看懂”系列。

玄机-第一章 应急响应-webshell查杀

作者是个垃圾,第一次玩玄机太紧张了,不知道flag是啥样找了半天,第二次开靶机多次尝试才知道格式。争取下次一次过。 靶机账号密码 root xjwebshell 1.黑客webshell里面的flag flag{xxxxx-xxxx-xxxx-xxxx-xxxx} 2.黑客使用的什么工具的shell github地址的md5 flag{md5} 3.黑客…

WordPress标签如何实现批量自定义链接

网站外链和内链都是非常重要的一项 SEO 工作,并且一个网站的反链建设也并非一朝一夕就能够做好,而是日积月累的增加才会更有优化效果,且不论是否为 nofollow 或者 dofollow 属性,对于很 SEOer 来说可能觉得建设 Do Follow 的反链更有用,但是我们不妨换个 SEO 思维方式,一…

Modbus转Ethernet IP网关模块与汇川PLC通讯在网关配置软件中的配置

通过Modbus转Ethernet/IP网关模块XD-MDEP100,实现汇川PLC与多种品牌Modbus设备的无缝通信,提高系统效率和稳定性。配置软件GWModbusBuilder完成网关与PLC通讯设置,支持EtherNet/IP协议,实现数据快速传输和实时监控。通过Modbus转Ethernet/IP网关模块(XD-MDEP100),可以实…

JavaScript系列:JS实现复制粘贴文字以及图片

目录一. 基于 Clipboard API 复制文字(推荐)基本概念主要方法使用限制实际应用示例二、基于 document.execCommand(copy)缺陷实际应用示例说明三、复制图片功能四、封装 一. 基于 Clipboard API 复制文字(推荐) 基本概念 Clipboard API 是一组用于在浏览器中操作剪贴板的 J…

数据分享|R语言决策树和随机森林分类电信公司用户流失churn数据和参数调优、ROC曲线可视化|附代码数据

原文链接:http://tecdat.cn/?p=26868 最近我们被客户要求撰写关于电信公司用户流失的研究报告,包括一些图形和统计输出。 在本教程中,我们将学习覆盖决策树和随机森林。这些是可用于分类或回归的监督学习算法 下面的代码将加载本教程所需的包和数据集。 library(tidyverse…