用go实现cors中间件

2023-11-15

目录

一、概述

二、简单请求和预检请求

简单请求

预检请求

三、使用go的gin框架实现cors配置

1、安装

2、函数


一、概述

        CORS(Cross-Origin Resource Sharing)是一种浏览器安全机制,用于控制在Web应用程序中不同源(Origin)之间的资源共享。一个源是由协议(例如http或https)、主机(例如 www.example.com)、以及端口(例如80或443)组成的组合。CORS允许服务器定义哪些源可以访问其资源,以及哪些HTTP方法和头部可以在跨源请求中使用。

要点:

  1. 同源策略(Same-Origin Policy):Web浏览器实施了同源策略,它限制了一个页面中加载的资源只能来自相同的源,以防止而已站点获取用户的敏感信息。这意味着默认情况下,跨域请求是被浏览器禁止的。
  2. 跨源HTTP请求:当一个Web页面需要从不同源的服务器获取数据时,例如通过AJAX请求或嵌入其他站点的资源(如字体、图片或脚本),就会设计到跨源HTTP请求。
  3. CORS解决跨域问题: CORS是一种机制,允许服务器在响应中添加HTTP标头来指示浏览器允许跨域请求。这些标头包括”Access-Control-Allow-Origin“、”Access-Control-Allow-Methods“、”Access-Control-Allow-Headers“等
  4. 简单请求和预检请求:浏览器将跨域HTTP请求分为两种类型:简单请求(Simple Request)和预检请求(Preflight Request)。简单请求就是常见的GET、POST请求,而预检请求时一种用于检查服务器是否支持某些请求的OPTION请求。
  5. 服务器配置:CORS的服务器配置通常在服务器端完成。服务器需要响应OPTIONS请求并在响应头中包含CORS标头来指定允许的来源、HTTP方法和头部。服务器还可以选择性地要求携带凭据(credentials)
  6. 浏览器行为:浏览器在发送跨域请求时会自动附加Origin头,然后根据服务器的响应判断是否允许访问资源。如果CORS设置不正确,浏览器会阻止页面访问响应的数据。

二、简单请求和预检请求

简单请求

1、判定条件

需要同时满足以下条件,浏览器会认为它是一个简单请求

  • 请求方法属于其中一种:GET、POST、HEAD
  • 请求包仅包含安全的字段,常见字段:Accept、Accept-Language、Content-Language、Content-Type、DPR、Downlink、Save-Data、Viewport-Width、Width
  • 请求头如果包含Content-Type,仅限如下值:text/plain、multipart/form-data、application/x-www-form-urlencoded

2、简单请求交互

①当浏览器判某个跨域请求时简单请求时,会在请求头中自动添加Origin字段

GET /cors HTTP/1.1
Host: example.com
Connection: keep-alive
...
Referer: http://local.com/index.html
Origin: http://local.com //Origin字段会告诉服务器,是哪个源地址在跨域请求

②服务器响应头中应包含Access-Control-Allow-Origin ,当服务器收到请求后,如果允许改请求跨域访问,需要在响应头中添加Access-Control-Allow-Origin字段

HTTP/1.1 200 OK
Date: Tue, 21 Jun 2023 08:03:35 GMT
...
Access-Control-Allow-Origin: http://local.com
...

消息体中的数据

当浏览器看到服务器允许自己访问后,于是,它就把响应顺利的交给js

预检请求

1、对于预检请求,请求步骤如下:

  • 浏览器发送预检请求,询问服务器是否允许
  • 服务器响应是否允许
  • 浏览器发送真实请求
  • 服务器完成真实的响应

2、步骤请求演示

要发送的请求包:

POST /cors HTTP/1.1

Host: example.com

Connection: keep-alive ...

Referer: http://local.com/index.html

Origin: http://local.com

{"name": "admin", "age": 20}

①浏览器发送预检请求

OPTIONS /cors HTTP/1.1
Host: example.com
...
Origin: http://local.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: a, b, content-type

ps:这并非想要发出的真实请求,请求中不包含响应头和也没有消息体。

预检请求特征:

请求方法为OPTIONS 没有请求体

  • 请求头中包含 Origin:请求的源,和简单请求的含义一致
  • Access-Control-Request-Method:后续的真实请求将使用的请求方法
  • Access-Control-Request-Headers:后续的真实请求会改动的请求头

②服务器允许

服务器收到预检请求后,可以检查预检请求中包含的信息,如果允许这样的请求,需要响应下面的消息格式

HTTP/1.1 200 OK
...
Access-Control-Allow-Origin: http://local.com
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: a, b, content-type
Access-Control-Max-Age: 86400
...

对于预检请求,不需要响应任何的消息体,只需要在响应头中添加: 

Access-Control-Allow-Origin:和简单请求一样,表示允许的源 Access-Control-Allow-Methods:表示允许的后续真实的请求方法 Access-Control-Allow-Headers:表示允许改动的请求头 Access-Control-Max-Age:告诉浏览器,多少秒内,对于同样的请求源、方法、头,都不需要再发送预检请求了

③浏览器发送真实请求

预检被服务器允许后,浏览器就会发送真实请求了,上面的代码会发送下面的请求数据

POST /cors HTTP/1.1

Host: example.com

Connection: keep-alive ...

Referer: http://local.com/index.html

Origin: http://local.com



{"name": "admin", "age": 20}

④服务器响应真实请求

HTTP/1.1 200 OK
Date: Tue, 21 Jun 2023 08:03:35 GMT
...
Access-Control-Allow-Origin: http://local.com
...

添加用户成功

三、使用go的gin框架实现cors配置

使用go的gin框架的话,说白了就是添加一个中间件,Gin官方提供CORS中间件,可以很方便的使用 cors解决跨域问题。

1、安装

使用命令安装该中间件

go get github.com/gin-contrib/cors

2、函数

cors中间件提供三个函数,代表三种使用方式,分别是NEWDefaultConfigDefault

  • NEW方式

可以接收 CORS 中间件的配置项,可通过自定义配置项,满足任意需要跨域的场景。

示例:
router.Use(cors.New(cors.Config{
    AllowOrigins:     []string{"https://foo.com"},
    AllowMethods:     []string{"PUT", "PATCH"},
    AllowHeaders:     []string{"Origin"},
    ExposeHeaders:    []string{"Content-Length"},
    AllowCredentials: true,
    AllowOriginFunc: func(origin string) bool {
      return origin == "https://github.com"
    },
    MaxAge: 12 * time.Hour,
  }))
//New 函数接收配置项,返回一个用户自定义的 CORS 中间件,绑定到路由中。

配置项说明:

  • AllowAllOrigins bool 允许所有请求源。
  • AllowOrigins []string 指定允许请求源的列表,如果列表中存在 *,则允许所有请求源,默认值是 []
  • AllowOriginFunc func(origin string) bool 接收参数 origin,函数体中的验证逻辑返回是否允许跨域请求。该配置项优先级高于 AllowOrigins []string,如果设置该配置项,AllowOrigins []string 配置项的设置被忽略。
  • AllowMethods []string 允许的请求方式,默认值是 GETPOSTPUTPATCHDELETEHEAD,和 OPTIONS
  • AllowHeaders []string 用在对预请求的响应中,指示实际的请求中可以使用哪些 HTTP 请求头。
  • AllowCredentials bool 表示请求附带请求凭据时是否响应请求,例如 cookieHTTP authentication 或客户端 SSL 证书
  • ExposeHeaders []string 可以在响应中显示的请求头。
  • MaxAge time.Duration 指示预请求的结果能被缓存多久。
  • AllowWildcard bool 添加请求源是否允许使用通配符,例如 http://some-domain/*https://api.http://some.*.subdomain.com
  • AllowBrowserExtensions bool 允许使用常用的浏览器的扩展模式。
  • AllowWebSockets bool 允许使用 WebSocket 协议。
  • AllowFiles bool 允许使用 file:// 协议。
  • DefaultConfig方式

默认设置一些通用配置项,我们可以直接使用,也可以在此基础上添加我们需要的其他配置项。

func DefaultConfig() Config {
 return Config{
  AllowMethods:     []string{"GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"},
  AllowHeaders:     []string{"Origin", "Content-Length", "Content-Type"},
  AllowCredentials: false,
  MaxAge:           12 * time.Hour,
 }
}
  • Default方式

DefaultConfig 方式的基础上,设置 AllowAllOrigins 选项为 true,因为 DefaultConfig 方式默认不允许任意请求源,所以需要单独设置 AllowAllOrigins 选项为 true

func Default() gin.HandlerFunc {
 config := DefaultConfig()
 config.AllowAllOrigins = true
 return New(config)
}

3、某段配置代码分析

//设置cors中间件
func Cors() gin.HandlerFunc {
	return func(c *gin.Context) {
		method := c.Request.Method  //获取请求包的http请求方法
		origin := c.Request.Header.Get("Origin") //获取请求包的head头的Origin参数值
		var headerkeys []string
		for k := range c.Request.Header {
			headerkeys = append(headerkeys, k)
		}
		headerStr := strings.Join(headerkeys, ", ") //将请求包中head头部分的参数用","连接成字符串


        //检查请求头不为空
		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"
		}
        //检查请求头中origin是否为空
		if origin != "" {
            //设置响应头中的"Access-Control-Allow-Origin"字段,允许任何域名访问资源(这是一个简单的CORS策略,实际应用中可能需要更严格的控制)。
			c.Writer.Header().Set("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!")
		}

	}
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

用go实现cors中间件 的相关文章

  • 基于java的物流信息网系统设计与实现

    基于java的物流信息网系统设计与实现 I 引言 A 研究背景和动机 基于Java的物流信息网系统设计与实现的研究背景和动机 随着互联网的普及和电子商务的快速发展 物流信息网系统已成为现代物流管理的重要组成部分 物流信息网系统能够实现物流信
  • 【计算机毕业设计】白优校园社团网站的设计与实现

    近些年 随着中国经济发展 人民的生活质量逐渐提高 对网络的依赖性越来越高 通过网络处理的事务越来越多 随着白优校园社团网站的常态化 如果依然采用传统的管理方式 将会为工作人员带来庞大的工作量 这将是一个巨大考验 需要投入大量人力开展对社团
  • 【gee】下载modis土地利用类型

    var china ee FeatureCollection projects assets china boundary var lc dataset ee ImageCollection MODIS 061 MCD12Q1 filter
  • 计算机Java项目|基于SSM的微课学习系统

    作者主页 编程指南针 作者简介 Java领域优质创作者 CSDN博客专家 CSDN内容合伙人 掘金特邀作者 阿里云博客专家 51CTO特邀作者 多年架构师设计经验 腾讯课堂常驻讲师 主要内容 Java项目 Python项目 前端项目 人工智
  • 计算机Java项目|在线图书管理

    作者简介 Java领域优质创作者 CSDN博客专家 CSDN内容合伙人 掘金特邀作者 阿里云博客专家 51CTO特邀作者 多年架构师设计经验 腾讯课堂常驻讲师 主要内容 Java项目 Python项目 前端项目 人工智能与大数据 简历模板
  • Python 文件的复制重命名以及xlsx文件中表格分开保存

    1 需要的头文件 import shutil import os import openpyxl 2 复制文件以及重命名 直接使用shutil库复制 重命名 移动即可 函数封装示例 source path 为全局变量被复制文件路径 dest
  • 计算机Java项目|学生成绩管理系统

    作者简介 Java领域优质创作者 CSDN博客专家 CSDN内容合伙人 掘金特邀作者 阿里云博客专家 51CTO特邀作者 多年架构师设计经验 腾讯课堂常驻讲师 主要内容 Java项目 Python项目 前端项目 人工智能与大数据 简历模板
  • 2024史上最全Java面试八股文(带全部答案)

    今天要谈的主题是关于求职 求职是在每个技术人员的生涯中都要经历多次 对于我们大部分人而言 在进入自己心仪的公司之前少不了准备工作 有一份全面细致 面试题 将帮助我们减少许多麻烦 在跳槽季来临之前 特地做这个系列的文章 一方面帮助自己巩固下基
  • 【go语言】AST抽象语法树详解&实践之扫描代码生成错误码文档

    背景 为了能识别出代码中抛出错误码的地址和具体的错误码值 再根据错误码文件获取到错误码的具体值和注释 方便后续的排错 这里使用AST进行语法分析获取到代码中的目标对象 一 编译过程 在开始解析代码之前先补充了解一下编译过程 编译过程是将高级
  • 你的服务器还安全吗?用户数据是否面临泄露风险?

    一系列严重的网络安全事件引起了广泛关注 多家知名公司的服务器遭到黑客挟持 用户的个人数据和敏感信息面临泄露的风险 这些事件揭示了网络安全的脆弱性和黑客攻击的威胁性 提醒着企业和个人加强对网络安全的重视 一 入侵案例 1 1 蔚来数据泄露 1
  • 【心电图基线估计和去噪方法的群稀疏正则化】带有群稀疏正则化的心电图基线估计和去噪(Matlab实现)

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 参考文献 4 Matlab代码及文章
  • 网络安全(黑客)自学启蒙

    一 什么是网络安全 网络安全是一种综合性的概念 涵盖了保护计算机系统 网络基础设施和数据免受未经授权的访问 攻击 损害或盗窃的一系列措施和技术 经常听到的 红队 渗透测试 等就是研究攻击技术 而 蓝队 安全运营 安全运维 则研究防御技术 作
  • 【路径规划】基于改进遗传算法求解机器人栅格地图路径规划(Matlab实现实现)

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 参考文献 4 Matlab代码实现
  • 为什么这么多人自学黑客,但没过多久就放弃了(掌握正确的网络安全学习路线很重要)

    网络安全是一个 不断发展和演变 的领域 以下是一个 网络安全学习路线规划 旨在帮助初学者快速入门和提高自己的技能 基础知识 网络安全的 基础知识 包括 网络结构 操作系统 编程语言 等方面的知识 学习这些基础知识对理解网络安全的原理和技术至
  • 【C#】基础巩固

    最近写代码的时候各种灵感勃发 有了灵感 就该实现了 可是 实现起来有些不流畅 总是有这样 那样的卡壳 总结下来发现了几个问题 1 C 基础内容不是特别牢靠 理解的不到位 导致自己想出来了一些内容 但是无法使用正确的C 代码实现 导致灵感无法
  • 2024最强Java面试八股文合集(持续更新)

    今天要谈的主题是关于求职 求职是在每个技术人员的生涯中都要经历多次 对于我们大部分人而言 在进入自己心仪的公司之前少不了准备工作 有一份全面细致 面试题 将帮助我们减少许多麻烦 在跳槽季来临之前 特地做这个系列的文章 一方面帮助自己巩固下基
  • sychnorized积累

    sychnorized 1 对象锁 包括方法锁 默认锁对象为this 当前实例对象 和同步代码块锁 自己指定锁对象 2 类锁 指synchronize修饰静态的方法或指定锁对象为Class对象 3 加锁和释放锁的原理 现象 时机 内置锁th
  • Java开发中不要使用受检异常

    简介 Java是唯一 主流 实现了受检异常概念的编程语言 一开始 受检异常就是争议的焦点 在当时被视为一种创新概念 Java于1996年推出 如今却被视不良实践 本文要讨论Java中非受检异常和受检异常的动机以及它们优缺点 与大多数关注这个
  • 计算机Java项目|java游戏账号交易系统

    作者简介 Java领域优质创作者 CSDN博客专家 CSDN内容合伙人 掘金特邀作者 阿里云博客专家 51CTO特邀作者 多年架构师设计经验 腾讯课堂常驻讲师 主要内容 Java项目 Python项目 前端项目 人工智能与大数据 简历模板
  • 网络安全行业热门认证证书合集

    网络安全认证证书 就和学历一样是敲门砖 拿到了可以用不到 但不能没有 技术大牛可以没有证书 但普通人不能没有 1 初级入门 就像学历在职场上展示一个人的基本素养一样 网络安全认证证书可以展示一个人在网络安全领域具备的基本知识和技能 它为初学

随机推荐