Gin框架跨域问题:Response to preflight request doesn‘t pass access control check:No ‘Access-Control-Allow..
在实现Gin框架对接前端时,通过axios发送对应的请求后发现对应的错误,通过查询后得知出现跨域资源共享(CORS)策略的限制,导致请求被阻止。具体原因是后端的响应没有包含 Access-Control-Allow-Origin 头,浏览器因此拒绝了请求。
1.什么是跨域?
跨域是指从一个域名(origin)向另一个不同域名发起的请求。这些不同可以表现在三个方面之一:
- 协议(例如,
http://和https://是不同的协议)。 - 域名(例如,
example.com和api.example.com是不同的域名)。 - 端口(例如,
http://example.com:80和http://example.com:8080是不同的端口)。
当你在一个网页中通过 JavaScript 发起 HTTP 请求(例如通过 XMLHttpRequest 或 Fetch API)时,如果请求的目标地址与当前网页的地址不属于同一个 origin,就会发生跨域请求。
2.为什么会有跨域问题?
跨域问题的核心是浏览器的同源策略(Same-Origin Policy)。同源策略是浏览器的一种安全机制,它阻止一个域的网页对另一个域的资源进行不受限制的访问。比如,防止恶意网站读取用户登录其他网站的敏感信息。
为了打破这种限制,并且允许合法的跨域请求,CORS 被引入。
3.CORS 的工作原理
CORS 通过 HTTP 头部让服务器告诉浏览器它允许哪些跨域请求。CORS 的工作机制大致如下:
-
简单请求:如果请求满足一定条件(例如使用
GET或POST方法,并且请求头不包含自定义的头部字段),浏览器会直接发送请求,并根据服务器返回的响应头判断是否允许跨域。如果服务器在响应中包含Access-Control-Allow-Origin头,并且该头的值匹配请求的来源(origin),浏览器就允许该跨域请求。 -
预检请求(Preflight Request):对于非简单请求(例如使用
PUT、DELETE方法,或携带复杂的自定义头部),浏览器会首先发送一个OPTIONS请求来检查服务器是否允许跨域。这种OPTIONS请求称为预检请求。服务器需要在响应中提供合适的 CORS 头,告知浏览器可以执行后续的实际请求。服务器需要返回以下一些头部字段:
Access-Control-Allow-Origin:指定哪些域可以访问资源。Access-Control-Allow-Methods:指定允许的 HTTP 方法。Access-Control-Allow-Headers:指定哪些自定义头部字段可以使用。Access-Control-Allow-Credentials:是否允许携带用户凭证(如 Cookies)。
-
凭证支持:如果跨域请求需要携带用户的凭证信息(如 Cookies、HTTP 身份验证),服务器需要在响应中包含
Access-Control-Allow-Credentials: true,并且前端请求也需要设置credentials: 'include'。 -
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,
}))
}
代码说明
AllowOrigins:用于设置允许跨域访问的前端域名。在开发环境中,常见的是允许localhost,确保你的前端能够正确访问后端 API。AllowMethods:控制允许使用的 HTTP 方法。为了确保前端能正确与后端通信,你需要明确列出允许的方法。AllowHeaders:用于指定前端请求时允许使用的自定义头部字段,特别是一些身份验证相关的头部字段。ExposeHeaders:决定前端能否访问某些响应头字段。在这个配置中,你让前端可以访问Content-Length,以便获取响应内容的长度。AllowCredentials:确保在跨域请求中能够发送凭证信息,如cookies,这对于需要用户认证的应用程序至关重要。MaxAge:这是性能优化的关键,设置预检请求的缓存时间,减少跨域请求的频繁预检操作。
通过实践后目前未出现其他问题。
更多推荐

所有评论(0)