Go 中 CORS 解决跨域问题
跨域问题
跨域问题 是由浏览器的 同源策略(Same-Origin Policy) 引起的安全限制。当网页尝试访问不同源(协议、域名、端口任一不同)的资源时,浏览器会阻止该请求,除非目标服务器明确允许跨域访问。
同源策略示例
- 同源:
http://a.com
和http://a.com/api
(协议、域名、端口相同) - 跨域:
http://a.com
访问https://a.com
(协议不同)、http://a.com
访问http://b.com
(域名不同)、http://a.com:80
访问http://a.com:8080
(端口不同)
CORS(跨源资源共享)
CORS (Cross-Origin Resource Sharing)是一种 W3C 标准机制,允许服务器声明哪些外部源可以访问其资源。浏览器通过 预检请求(Preflight Request)(OPTIONS
方法)验证权限,服务器需响应特定的 HTTP 头来授权。
- 简单请求(Simple Request)
当请求满足以下条件时,浏览器直接发送请求,并在响应头中检查Access-Control-Allow-Origin
:- 方法为
GET
、POST
、HEAD
- 请求头仅包含允许的标头(如
Accept
、Content-Type
等) Content-Type
为text/plain
、multipart/form-data
或application/x-www-form-urlencoded
- 方法为
- 预检请求(Preflight Request)
对于不满足简单请求条件的请求(如PUT
、DELETE
或自定义请求头),浏览器会先发送一个OPTIONS
方法的预检请求,验证服务器是否允许实际请求。
关键 HTTP 头
Access-Control-Allow-Origin
: 允许的源(如http://a.com
或*
)Access-Control-Allow-Methods
: 允许的 HTTP 方法(如GET, POST
)Access-Control-Allow-Headers
: 允许的请求头(如Content-Type
)Access-Control-Allow-Credentials
: 是否允许携带凭据(如 Cookies)
Go 中解决跨域的两种方式
1. 手动设置响应头(适合简单场景)
package main
import (
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
// 设置 CORS 头
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
if r.Method == "OPTIONS" {
w.WriteHeader(http.StatusOK)
return
}
w.Write([]byte("Hello, CORS!"))
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
2. 使用 rs/cors
中间件(推荐)
package main
import (
"net/http"
"github.com/rs/cors"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello, CORS with Middleware!"))
})
// 配置 CORS 中间件
c := cors.New(cors.Options{
AllowedOrigins: []string{"http://localhost:3000", "https://your-app.com"},
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE"},
AllowedHeaders: []string{"Content-Type", "Authorization"},
AllowCredentials: true,
MaxAge: 86400, // 预检请求缓存时间(秒)
})
handler := c.Handler(mux)
http.ListenAndServe(":8080", handler)
}
关键配置说明
- AllowedOrigins:指定允许访问的域名列表,生产环境应避免使用
*
。 - AllowedMethods:声明支持的 HTTP 方法。
- AllowedHeaders:允许客户端发送的非简单头部(如自定义头)。
- AllowCredentials:设为
true
时,前端需设置withCredentials: true
(如携带 Cookies)。 - MaxAge:减少预检请求次数,提升性能。