Day22 Gin with CORS

What is CORS

CORS全名为Cross-Origin Resource Sharing 跨来源资源共用,是种使用额外HTTP Header令目前浏览网站的使用者代理能够取得其他网域四奇异资源的机制,当使用者代理乞求一个不是当前文件来源的资源(different domain, different protocol or different port...etc)时,会建立一个跨来源请求(Cross-Orgin HTTP Request)。

像是目前前後端分离的开发方式、前端页面CSS、Image以及Script的Import以及CDN等,都是跨来源请求的例子,而基於安全性考量,这些Request都会受到限制。如果不使用CORS的Header将不能请求不同网域的HTTP资源。

https://ithelp.ithome.com.tw/upload/images/20211007/20129737DljZ9D0421.png

CORS机制使我们能够安全有效地进行跨网域请求,那什麽类型的requests会需要启用CORS支援呢

  • 不同的网域:像是从 abc.com123.com
  • 不同的子网域:像是从 abc.comcde.abc.com
  • 不同的port:像是从 abc.comabc.com:8888
  • 不同的通讯协定:像是从 https://abc.comhttp://abc.com

CORS Request可分为两种,简单请求与非简单请求

如果以下条件皆符合,那该HTTP 请求为简单请求:

  • 它是针对只允许 GETHEAD 和 POST 请求的 API 资源所发出的。
  • 如果它是 POST 方法请求,则必须包含 Origin 标头。
  • 请求承载内容类型为 text/plainmultipart/form-data 或 application/x-www-form-urlencoded
  • 请求不包含自订标头。

对於简单的跨来源 POST 方法请求,来自您资源的回应需要包括标头 Access-Control-Allow-Origin,其中标头金钥的值会设为 '*'(任何来源),或设定为允许存取该资源的来源。

所有其他跨来源 HTTP 请求都是非简单请求。如果您的 API 资源接收非简单请求,您将需要启用 CORS 支援。

Gin with CORS

Installation

go get github.com/gin-contrib/cors

Allow all CORS Resource

func main() {
  server := gin.Default()
	corsConfig := cors.DefaultConfig()
	corsConfig.AllowAllOrigins = true
	server.Use(cors.New(corsConfig))
  server.Run()
}
  • AllowAllOrigins: 允许所有的CORS请求

Allow Specific CORS Resource

func main() {
	server := gin.Default()
	corsConfig := cors.DefaultConfig()
	corsConfig.AllowOrigins = []string{"https://google.com", "https://facebook.com"}
	corsConfig.AllowMethods = []string{"GET", "POST", "PUT"}
	corsConfig.AllowHeaders = []string{"Authorization", "Origin"}
	corsConfig.AllowCredentials = true
	corsConfig.ExposeHeaders = []string{"Content-Length"}
	corsConfig.MaxAge = 12 * time.Hour
	server.Use(cors.New(corsConfig))
}

这边讲解一下几个主要的设定:

  • AllowOrigins: 允许的domain
  • AllowMethods: 允许的HTTP Method
  • AllowHeaders: 允许的Header 信息
  • AllowCredentials: 是否允许请求包含验证凭证
  • ExposeHeaders: 允许暴露的Header信息
  • MaxAge: 可被存取的时间

Gin with CORS Middleware

接下来我们将CORS Settings包装成一个Middleware让 gin.Default() 做使用。

app/middleware/cors.go

func CORSMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
        c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
        c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With")
        c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT")

        if c.Request.Method == "OPTIONS" {
            c.AbortWithStatus(204)
            return
        }

        c.Next()
    }
}

main.go

gin这边记得要调用这个middleware,如此一来就完成了。

server.Use(middleware.CORSMiddleware())

Summary

由於上个章节刚刚结束了JWT实作在Gin上的部分,因此这章节立马来解说使用JWT Token上常常会遇到的一个Issue 跨域问题! 那这边除了解说CORS原理外,同时也立马写了个CORS的Middleware并加进Gin中,完成实作。

程序码的部分我也会放到下方连结,有兴趣者欢迎Pull来学习或使用。

https://github.com/Neskem/Ironman-2021/tree/Day-22

Reference

https://buddhiv.medium.com/what-is-cors-or-cross-origin-resource-sharing-eccbfacaaa30

https://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/how-to-cors.html


<<:  Day 25 : XGBoost

>>:  找LeetCode上简单的题目来撑过30天啦(DAY22)

#03 No-code 之旅 — 什麽是 SSG、SSR、CSR、ISR?

嗨大家!连假第一天过得如何?~ 今天想跟大家分享的主题是各种网页渲染模式,就是 SSG、SSR、CS...

[Day 11] 简单的单元测试实作(五)

接下来我们要测试100的倍数, 我们这次直接加两个数字, public function input...

Dungeon Mizarka 028

衔接VS和UI 好不容易掌握了UI架构的概念,也开始依照这个想法和VS进行接合,但UI架构里出现了很...

Day 19 Provider小Tips

今天是一个小Tip的日子,当我们在座每项测试案例时,不可能每次都要包Provider吧 太累 imp...

[Day 23] 让tinyML感受你的律动

话说为了要作出吃了会考试100分、会变聪明、变漂亮的「爆浆濑尿虾牛丸」,我特别找来庙街最重情义的火鸡...