在实现Gin框架对接前端时,通过axios发送对应的请求后发现对应的错误,通过查询后得知出现跨域资源共享(CORS)策略的限制,导致请求被阻止。具体原因是后端的响应没有包含 Access-Control-Allow-Origin 头,浏览器因此拒绝了请求。

1.什么是跨域?

跨域是指从一个域名(origin)向另一个不同域名发起的请求。这些不同可以表现在三个方面之一:

  1. 协议(例如,http://https:// 是不同的协议)。
  2. 域名(例如,example.comapi.example.com 是不同的域名)。
  3. 端口(例如,http://example.com:80http://example.com:8080 是不同的端口)。

当你在一个网页中通过 JavaScript 发起 HTTP 请求(例如通过 XMLHttpRequest 或 Fetch API)时,如果请求的目标地址与当前网页的地址不属于同一个 origin,就会发生跨域请求。

2.为什么会有跨域问题?

跨域问题的核心是浏览器的同源策略(Same-Origin Policy)。同源策略是浏览器的一种安全机制,它阻止一个域的网页对另一个域的资源进行不受限制的访问。比如,防止恶意网站读取用户登录其他网站的敏感信息。

为了打破这种限制,并且允许合法的跨域请求,CORS 被引入。

3.CORS 的工作原理

CORS 通过 HTTP 头部让服务器告诉浏览器它允许哪些跨域请求。CORS 的工作机制大致如下:

  1. 简单请求:如果请求满足一定条件(例如使用 GETPOST 方法,并且请求头不包含自定义的头部字段),浏览器会直接发送请求,并根据服务器返回的响应头判断是否允许跨域。如果服务器在响应中包含 Access-Control-Allow-Origin 头,并且该头的值匹配请求的来源(origin),浏览器就允许该跨域请求。

  2. 预检请求(Preflight Request):对于非简单请求(例如使用 PUTDELETE 方法,或携带复杂的自定义头部),浏览器会首先发送一个 OPTIONS 请求来检查服务器是否允许跨域。这种 OPTIONS 请求称为预检请求。服务器需要在响应中提供合适的 CORS 头,告知浏览器可以执行后续的实际请求。

    服务器需要返回以下一些头部字段:

    • Access-Control-Allow-Origin:指定哪些域可以访问资源。
    • Access-Control-Allow-Methods:指定允许的 HTTP 方法。
    • Access-Control-Allow-Headers:指定哪些自定义头部字段可以使用。
    • Access-Control-Allow-Credentials:是否允许携带用户凭证(如 Cookies)。
  3. 凭证支持:如果跨域请求需要携带用户的凭证信息(如 Cookies、HTTP 身份验证),服务器需要在响应中包含 Access-Control-Allow-Credentials: true,并且前端请求也需要设置 credentials: 'include'

  4. Cores头部示例:

Access-Control-Allow-Origin: http://example.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Allow-Credentials: true

4.在Gin框架中解决跨域问题:

了解完跨域之后我们就可以解决这个问题:

我们可以使用第三方中间件Cores来解决这个问题

Cores是什么?

    gin-contrib/cors 是一个用于 Gin 框架的 CORS 中间件库,它提供了方便的 API 让你能够轻松配置和管理 CORS 设置。这个库专门为 Gin 框架设计,和 Gin 的中间件机制无缝集成。

代码实践:

import (
	"github.com/gin-contrib/cors"
)

func main(){
r := gin.Default()
// 使用 Gin 的中间件机制,添加 CORS 中间件
r.Use(cors.New(cors.Config{
    // AllowOrigins: 指定允许跨域访问的前端地址(Origin)。只允许这些来源的请求通过。
    // 这里设置为 http://localhost:8080,意味着只允许来自这个地址的前端页面访问后端 API。
    AllowOrigins: []string{"http://localhost:8080"},

    // AllowMethods: 定义允许的 HTTP 方法列表,这些方法在跨域请求中被允许使用。
    // 这里允许了常见的 HTTP 请求方法:GET(读取数据)、POST(提交数据)、PUT(更新数据)、DELETE(删除数据)、OPTIONS(预检请求)。
    AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},

    // AllowHeaders: 指定允许在跨域请求中使用的 HTTP 头部字段。
    // 这里允许了 Origin(请求来源)、Authorization(身份验证头部,如 Token)、Content-Type(请求内容类型)。
    AllowHeaders: []string{"Origin", "Authorization", "Content-Type"},

    // ExposeHeaders: 指定哪些响应头部字段可以被前端 JavaScript 代码访问。
    // 默认情况下,浏览器只能访问某些基本的头部字段,这里通过设置 ExposeHeaders 暴露了 Content-Length 字段,
    // 这样前端可以获取到响应数据的长度信息。
    ExposeHeaders: []string{"Content-Length"},

    // AllowCredentials: 允许跨域请求中携带凭证(如 Cookies 或 HTTP 认证信息)。
    // 设置为 true 时,前端请求中可以包含凭证信息,这对于需要用户身份验证的请求非常有用。
    // 注意:当设置 AllowCredentials 为 true 时,AllowOrigins 不能设置为 '*',必须是明确的域名列表。
    AllowCredentials: true,

    // MaxAge: 指定浏览器可以缓存 CORS 预检请求的时间,减少不必要的预检请求,提升性能。
    // 这里设置为 12 小时,意味着在这段时间内,相同的跨域请求不会再触发预检请求。
    MaxAge: 12 * time.Hour,
}))

}

代码说明

  1. AllowOrigins:用于设置允许跨域访问的前端域名。在开发环境中,常见的是允许 localhost,确保你的前端能够正确访问后端 API。
  2. AllowMethods:控制允许使用的 HTTP 方法。为了确保前端能正确与后端通信,你需要明确列出允许的方法。
  3. AllowHeaders:用于指定前端请求时允许使用的自定义头部字段,特别是一些身份验证相关的头部字段。
  4. ExposeHeaders:决定前端能否访问某些响应头字段。在这个配置中,你让前端可以访问 Content-Length,以便获取响应内容的长度。
  5. AllowCredentials:确保在跨域请求中能够发送凭证信息,如 cookies,这对于需要用户认证的应用程序至关重要。
  6. MaxAge:这是性能优化的关键,设置预检请求的缓存时间,减少跨域请求的频繁预检操作。

通过实践后目前未出现其他问题。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐