【Golang】Gin框架中跨域问题解决方案

在这里插入图片描述

✨✨ 欢迎大家来到景天科技苑✨✨

🎈🎈 养成好习惯,先赞后看哦~🎈🎈

🏆 作者简介:景天科技苑
🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。
🏆《博客》:Python全栈,Golang开发,PyQt5和Tkinter桌面开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi,flask等框架,云原生K8S,linux,shell脚本等实操经验,网站搭建,数据库等分享。

所属的专栏:Go语言开发零基础到高阶实战
景天的主页:景天科技苑

在这里插入图片描述

文章目录

  • Gin框架中跨域问题解决方案
    • 一、引言
    • 二、跨域问题的基本概念
      • 1. 同源策略
      • 2. 跨域资源共享(CORS)
      • 3. 预检请求(Preflight Request)
    • 三、Gin框架中解决跨域问题的方法
      • 方法一:自定义中间件
      • 方法二:使用第三方库`github.com/gin-contrib/cors`
      • 方法三:JSONP请求(不推荐)
    • 四、总结

Gin框架中跨域问题解决方案

一、引言

在使用Go语言进行Web开发时,Gin框架因其简洁、高效的特点而被广泛使用。然而,在实际开发中,跨域问题(CORS, Cross-Origin Resource Sharing)是一个常见的挑战。跨域问题主要源于浏览器的同源策略(Same-Origin Policy),当一个网页尝试从不同的源(协议、域名或端口不同)请求资源时,就会产生跨域问题。本文将结合实际案例,详细介绍在Gin框架中解决跨域问题的多种方法。

二、跨域问题的基本概念

1. 同源策略

同源策略是浏览器的一种安全机制,用于限制一个源(协议、域名和端口)的文档或脚本如何与另一个源的资源进行交互。例如,一个在http://example.com上的网页不能从http://otherdomain.com加载数据,即使服务器响应了请求,浏览器也会阻止该请求返回的数据被脚本访问。

同源策略,是浏览器为了保护用户信息安全的一种安全机制。
所谓的同源就是指代通信的两个地址(例如服务端接口地址与浏览器客户端页面地址)之间比较,是否协议、域名和端口相同。
不同源的客户端脚本[javascript]在没有明确授权的情况下,没有权限读写对方信息。

同源策略机制(Same Origin Policy,SOP)是一种约定,它是浏览器最核心也是最基本的安全功能,如果缺少了同源策略。
则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础上的,浏览器只是针对同源策略的一种实现。

当一个浏览器的两个tab页中分别打开百度和谷歌的页面时,当浏览器的百度tab页执行一个脚本的时候会检查这个脚本是属于哪个页面的,即检查是否同源,只有和百度同源的脚本才会被执行。
如果非同源,那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。
不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。所以google.com下的js脚本采用ajax读取baidu.com里面的文件数据是会报错的。

跨域请求,首先浏览器为了安全,做了一个同源策略机制,也就是所谓的同源安全策略,本质上,其实是不存在所谓的跨不跨域的,
把浏览器想象成一个发送网络请求的软件,按照道理来说,请求都是可以发送出去的,但是在 web 端,浏览器里,这么做的就不合适,
如果网络上的接口可以不受限制的被任意人调用,那将是一个非常混乱的场景,所以,为了防止这种情况,浏览器做了这个同源策略来防止这种情况发生。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
总结:协议相同+域名相同+端口号相同,浏览器才认为是同一个网站,才不会受到同源策略的影响,才可以正常的发送Ajax请求。

所谓的同源策略是浏览器实现的,而和后台服务器无关,A 发送请求到 B. 请求实际上是发送到了 B 后台, B后台接受到数据后。
其实也有返回,只不过,这个数据返回到浏览器之后,浏览器把这个数据给劫持了,不让A网站使用

既然跨域这么麻烦,为什么要进行跨域?
因为当一个项目变大时,把所有的内容都丢在一个网站或者是后台服务器中是不现实的.

2. 跨域资源共享(CORS)

CORS是一种标准机制,允许Web应用程序在跨域访问资源时,通过设置特定的HTTP响应头来放宽浏览器的同源策略限制。

3. 预检请求(Preflight Request)

预检请求是CORS机制中的一部分,它是浏览器为了安全考虑而自动发起的一种请求,主要用于复杂的跨域请求前的“探路”。这种请求使用HTTP的OPTIONS方法,目的是为了确认服务器是否允许特定的跨域请求。

三、Gin框架中解决跨域问题的方法

方法一:自定义中间件

在Gin框架中,可以通过自定义中间件的方式来解决跨域问题。以下是一个自定义中间件的示例代码:

package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"net/http"
	"strings"
)

// 跨域中间件
func Cors() gin.HandlerFunc {
	return func(c *gin.Context) {
		method := c.Request.Method // 请求方法
		origin := c.Request.Header.Get("Origin") // 请求头部
		var headerKeys []string // 声明请求头keys
		for k, _ := range c.Request.Header {
			headerKeys = append(headerKeys, k)
		}
		headerStr := strings.Join(headerKeys, ", ")
		if headerStr != "" {
			headerStr = fmt.Sprintf("access-control-allow-origin, access-control-allow-headers, %s", headerStr)
		} else {
			headerStr = "access-control-allow-origin, access-control-allow-headers"
		}
		if origin != "" {
			c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
			c.Header("Access-Control-Allow-Origin", "*") // 允许访问所有域
			c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE") // 服务器支持的所有跨域请求的方法
			c.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token, session, X_Requested_With, Accept, Origin, Host, Connection, Accept-Encoding, Accept-Language, DNT, X-CustomHeader, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Pragma") // 允许的头类型
			c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Cache-Control, Content-Language, Content-Type, Expires, Last-Modified, Pragma, FooBar") // 允许跨域设置,可以返回其他子段
			c.Header("Access-Control-Max-Age", "172800") // 缓存请求信息,单位为秒
			c.Header("Access-Control-Allow-Credentials", "false") // 跨域请求是否需要带cookie信息,默认设置为true
			c.Set("content-type", "application/json") // 设置返回格式是json
		}
		// 放行所有OPTIONS方法
		if method == "OPTIONS" {
			c.JSON(http.StatusOK, "Options Request!")
		}
		// 处理请求
		c.Next()
	}
}

func main() {
	engine := gin.Default()
	// 允许使用跨域请求,全局中间件
	engine.Use(Cors())
	engine.Run(":11000") // 运行启动端口
}

在上述代码中,定义了一个名为Cors的中间件函数,该函数通过设置HTTP响应头来允许跨域请求。在main函数中,通过engine.Use(Cors())将中间件应用到全局路由上。

方法二:使用第三方库github.com/gin-contrib/cors

Gin框架自身并未内置CORS支持,但有一个官方推荐的、与Gin高度集成的第三方库github.com/gin-contrib/cors可以方便地解决这个问题。以下是使用第三方库解决跨域问题的步骤:

  1. 添加依赖
    在你的项目中添加github.com/gin-contrib/cors依赖:

    go get -u github.com/gin-contrib/cors
    
  2. 创建CORS配置
    创建一个cors.Config结构体实例,用于定义你的CORS策略。以下是一些常见的配置选项:

    package conf
    
    import (
        "github.com/gin-contrib/cors"
        "time"
    )
    
    var CorsConfig = cors.Config{
        AllowAllOrigins:  false,
        AllowOrigins:     []string{"http://localhost:3000"}, // 允许的源,生产环境中应替换为具体的允许域名
        AllowOriginFunc:  func(origin string) bool { return true }, // 自定义函数来判断源是否允许
        AllowMethods:     []string{"GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"}, // 允许的HTTP方法列表
        AllowHeaders:     []string{"Origin", "Content-Length", "Content-Type", "Authorization"}, // 允许的HTTP头部列表
        AllowCredentials: true,                             // 是否允许浏览器发送Cookie
        MaxAge:           10 * time.Minute,                 // 预检请求(OPTIONS)的缓存时间(秒)
    }
    
  3. 使用CORS中间件
    在Gin的路由器上应用CORS中间件:

    package main
    
    import (
        "github.com/gin-contrib/cors"
        "github.com/gin-gonic/gin"
        "goproject/conf" // 引入CORS配置
    )
    
    func main() {
        router := gin.Default()
        // 使用配置好的CORS规则
        router.Use(cors.New(conf.CorsConfig))
    
        // 定义路由
        router.GET("/ping", func(c *gin.Context) {
            c.JSON(200, gin.H{
                "message": "pong",
            })
        })
    
        router.Run(":8080") // 启动服务器
    }
    

在上述代码中,首先定义了CORS配置CorsConfig,然后在Gin路由器上通过router.Use(cors.New(conf.CorsConfig))应用了CORS中间件。这样,所有经过这个路由器的请求都会先经过CORS中间件的处理,自动添加相应的CORS响应头。

方法三:JSONP请求(不推荐)

JSONP是一种较老的技术,用于解决跨域问题。然而,由于其安全性和灵活性不如CORS,现代浏览器已逐渐弃用JSONP。因此,在可能的情况下,建议优先考虑实现CORS。然而,如果你需要支持旧版客户端或CORS不可行的特定场景,JSONP仍可作为一种可行的解决方案。

以下是一个使用JSONP的示例代码:

package main

import (
	"github.com/gin-gonic/gin"
)

func main() {
	router := gin.Default()

	// JSONP请求处理
	router.GET("/jsonp", func(c *gin.Context) {
		callback := c.Query("callback")
		data := map[string]interface{}{
			"title": "标题-jsonp",
			"desc":  "说明-jsonp",
			"content": "内容-jsonp",
		}
		c.JSONP(200, data)
	})

	router.Run(":8080")
}

在上述代码中,定义了一个/jsonp路由,该路由通过c.JSONP(200, data)方法返回JSONP响应。客户端可以通过添加callback参数来接收JSONP响应。

四、总结

跨域问题是Web开发中的一个常见问题,特别是在前后端分离的项目中。在Gin框架中,处理跨域问题可以通过自定义中间件、使用第三方库或JSONP等方式来实现。其中,使用自定义中间件和第三方库是两种常见且有效的方法。通过合理配置CORS策略,可以确保Web应用程序能够正确处理跨域请求,同时保障用户数据的安全。

在实际应用中,开发者应根据具体的安全需求和交互模式来配置CORS策略。例如,可以限制允许跨域请求的域名、方法、头部等,以确保只有符合条件的请求能够被处理。此外,还需要注意处理预检请求,以确保复杂的跨域请求能够成功通过。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python飞舞蝙蝠

目录 系列文章 写在前面 完整代码 代码分析 写在后面 系列文章 序号直达链接爱心系列1Python制作一个无法拒绝的表白界面2Python满屏飘字表白代码3Python无限弹窗满屏表白代码4Python李峋同款可写字版跳动的爱心5Python流星雨代码6Python漂浮爱心代码7Python爱心光波代码…

【SSM-Day5】SpringMVC入门

【SSM-Day5】SpringMVC入门 Web->Servlet->Servlet容器MVC档案SpringMVC档案SpringMVC核心操作📢建立连接RequestMapping:实现路由映射Controller/ResponseBody:表示某个类是否可以接收HTTP请求 📢接收请求1. 直接接收一个请…

ChatGPT在解读历史股票收益预测中的外推和错误校准

论文地址:https://arxiv.org/pdf/2408.16707 原本地址:https://mp.weixin.qq.com/s/gL8ZTnpS0xJy7Qc73QEaGw 摘要 本文研究了大型语言模型(LLM)如何解释历史股票回报,并将其预测与众包股票排名平台的估计进行了比较。…

binlog 介绍

公司使用的数据库是 glodendb https://www.zte.com.cn/china/solutions_latest/goldendb.html#idpart01 最近自动化投产对一张 28w 的表进行全表 update、投产前已经是知道这个数据量的、认为没有问题、也没有在测试环境进行测试。 结果投产那天直接报错 这个 transaction_max…

什么是x86架构,什么是arm架构

什么是 x86 架构? x86 架构是一种经典的指令集架构(ISA),最早由英特尔在 1978 年推出,主要用于 PC、服务器等领域。 它是一种复杂指令集计算(CISC)架构,支持大量的复杂指令和操作&…

18.04Ubuntu网络一直connecting的问题

有段时间没登VMware的Ubuntu了,就知道这个Ubuntu一登必有问题。 如果你的网络一直connecting 设置成桥接模式就可以了!

linux离线安装Ollama并完成大模型配置(无网络)

这篇文章主要分享两方面内容: 1)在纯内网环境下如何部署ollama 2)在纯内网环境下如何配置大模型 话不多说直接开始。 ①离线部署ollama 一、通过浏览器访问ollama官方安装脚本,获取脚本内容。复制里面的内容。 在Linux中执行…

Linux笔记---Makefile的简单用法

1. 什么是Makefile Makefile 是一种用于自动化构建和管理项目的工具,特别是在软件开发中非常常见。 它包含了一系列规则(rules)和指令,描述了如何编译和链接源代码文件,以及生成最终的可执行文件或库文件。 简单来说&a…

stm32入门教程--USART外设 超详细!!!

目录 简介 什么是UART? 什么是USART? 简介 USART(Universal Synchron /Asynchronous Receiver /Transmitter)通用同步/异步收发器 1、USART是STM32内部集成的硬件外设,可根据数据寄存器的一个字节数据自动生成数据帧…

启动任务节点时,传入机械臂参数

MoveIt2_tutorial-Examples-Planning Scene ROS API 先启动move_group节点,后启动任务节点 方式1: 直接传入参数文件的地址 from launch import LaunchDescription # 导入启动描述,用于描述启动文件的结构 from launch_ros.actions impor…

规划误差降低27%,碰撞率降低33%Senna: 大规模视觉-语言模型与端到端自动驾驶相结合

Abstract 端到端自动驾驶在大规模数据中展示了强大的规划能力,但在复杂、罕见的场景中仍然因常识有限而表现不佳。相比之下,大型视觉语言模型(LVLMs)在场景理解和推理方面表现出色。前进的方向在于融合两者的优势。以往利用LVLMs…

Charles简单压力测试

1.接口请求次数,并发量,请求延迟时间均可配置 1.1选中需要进行测试的接口,鼠标右键选中【repeat advance】 2.设置并发参数 下面的图中,选择了1个接口,每次迭代中1个接口同时请求,迭代1000次(…

Zookeeper 对于 Kafka 的作用是什么?

大家好,我是锋哥。今天分享关于【Zookeeper 对于 Kafka 的作用是什么?】面试题?希望对大家有帮助; Zookeeper 对于 Kafka 的作用是什么? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 ZooKeeper 在 Kafka…

【机器学习基础】激活函数

激活函数 1. Sigmoid函数2. Tanh(双曲正切)函数3. ReLU函数4. Leaky ReLU函数 1. Sigmoid函数 观察导数图像在我们深度学习里面,导数是为了求参数W和B,W和B是在我们模型model确定之后,找出一组最优的W和B,使…

leetcode-62-不同路径

题解: 1、设dp[i][j]代表到达(i,j)点最多的路径;题目要求机器人每次只能向右或向下走一步,所以到达(i,j)点的最多路径为到达(i-1,j)的最多路径与到达(i,j-1)的最多路径之和。即dp[i][j]dp[i-1][j]dp[i][j-1]。 2、初始化一个M*N的矩阵dp,将…

C++在实际项目中的应用第三节:C++与数据科学

第五章:C在实际项目中的应用 第三节:C与数据科学 1. C在数据分析中的实际应用 数据分析是数据科学的核心部分,主要涉及数据的清洗、转换和建模。C作为一种高性能的编程语言,越来越多地被应用于数据分析领域。以下是 C 在数据分…

Git上传文件至AtomGit

目录 一、GIt大文件存储 Git LFS 二、Git LFS的使用 1.初始化 2.将大型文件放进LFS管理 三、整体流程 首先,你已经创建属于你自己的本地库了。以下一大型文件上传为基础,50mb的文件可以直接上传至 AtomGit上面,不需要多讲。 一、GIt大文…

北京迅为iTOP-LS2K0500开发板快速使用编译环境虚拟机Ubuntu基础操作及设置

迅为iTOP-LS2K0500开发板 迅为iTOP-LS2K0500开发板采用龙芯LS2K0500处理器,基于龙芯自主指令系统(LoongArch)架构,片内集成64位LA264处理器核、32位DDR3控制器、2D GPU、DVO显示接口、两路PClE2.0、两路SATA2.0、四路USB2.0、一路…

ArcGIS005:ArcMap常用操作101-150例动图演示

摘要:本文涵盖了GIS软件操作的多方面内容,包括地图文档的新建、打开、保存及版本兼容性处理;错误与警告的查阅及帮助文档的使用技巧;地图打印比例尺的调整与地图信息的完善;图层操作的撤销与恢复,界面元素的…

设计模式基础概念(行为模式):责任链模式(Chain Of Responsibility)

概述 责任链模式是一种行为设计模式, 允许你将请求沿着处理者链进行发送。 收到请求后, 每个处理者均可对请求进行处理, 或将其传递给链上的下个处理者。 该模式建议你将这些处理者连成一条链。 链上的每个处理者都有一个成员变量来保存对于…