Go CORS
最后修改时间 2024 年 4 月 11 日
在本文中,我们定义了 CORS 并展示了如何在 Golang 中使用 CORS。
同源策略
浏览器强制执行同源策略,该策略允许网页中的 JS 脚本仅在两个网页具有相同源的情况下访问其他网页中的数据。一个源被定义为 URL 方案、主机名和端口号的组合。该策略有助于隔离潜在的恶意文档,从而减少可能的攻击向量。
CORS
跨域资源共享 (CORS) 是一种基于 HTTP 标头的过程,它定义了浏览器可以从哪些源加载资源。
CORS 通过使用 HTTP CORS 标头放宽了同源策略。
请求标头
- Origin - 指示服务器请求的来源
- Access-Control-Request-Method - 指示服务器请求实现哪些 HTTP 方法
- Access-Control-Request-Headers - 指示服务器请求包含哪些标头
响应标头
- Access-Control-Allow-Origin - 服务器允许的来源
- Access-Control-Allow-Methods - 服务器允许的方法的逗号分隔列表
- Access-Control-Allow-Headers - 服务器允许的标头的逗号分隔列表
- Access-Control-Expose-Headers - 客户端可以从响应中访问的标头的逗号分隔列表
- Access-Control-Max-Age - 告知浏览器将预检请求的响应缓存多长时间(以秒为单位)
- Access-Control-Allow-Credentials
Go CORS 简单示例
在下面的示例中,我们在 Go 服务器应用程序中启用了 CORS。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Home</title> </head> <body> <script> async function doRequest() { let url = 'https://:8080/hello'; let res = await fetch(url); if (res.ok) { let text = await res.text(); return text; } else { return `HTTP error: ${res.status}`; } } doRequest().then(data => { document.getElementById("output").innerText = data; }); </script> <div id="output"> </div> </body> </html>
在 HTML 网页中,我们使用 JS Fetch API 创建 GET 请求。该脚本读取响应并将其设置为输出 div 元素。要尝试此示例,请通过 nginx 等 Web 服务器加载此网页,或使用 liveserver VS Code 扩展。
package main import ( "fmt" "log" "net/http" ) func main() { http.HandleFunc("/hello", HelloHandler) log.Println("Listening...") log.Fatal(http.ListenAndServe(":8080", nil)) } func HelloHandler(w http.ResponseWriter, _ *http.Request) { w.Header().Set("Content-Type", "text/plain; charset=utf-8") w.Header().Set("Access-Control-Allow-Origin", "http://127.0.0.1:5501") w.Header().Set("Access-Control-Max-Age", "15") fmt.Fprintf(w, "Hello, there!") }
在 HelloHandler
中,我们为服务器设置了 CORS 策略。
log.Fatal(http.ListenAndServe(":8080", nil))
该应用程序在 localhost 的 8080 端口上运行。为了从其他来源访问此服务器的资源,需要启用它们。
w.Header().Set("Content-Type", "text/plain; charset=utf-8") w.Header().Set("Access-Control-Allow-Origin", "http://127.0.0.1:5501") w.Header().Set("Access-Control-Max-Age", "15")
我们为此服务器启用了 CORS 策略。来自 http://127.0.0.1:5501
源的 JS 脚本可以访问我们的资源。
Go CORS 处理程序
github.com/rs/cors
是一个第三方包,它定义了 net/http 处理程序,在 Golang 中实现了跨域资源共享 W3 规范。
package main import ( "fmt" "net/http" "github.com/rs/cors" ) func main() { mux := http.NewServeMux() cors := cors.New(cors.Options{ AllowedOrigins: []string{"*"}, AllowedMethods: []string{ http.MethodPost, http.MethodGet, }, AllowedHeaders: []string{"*"}, AllowCredentials: false, }) mux.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/plain; charset=utf-8") fmt.Fprintln(w, "Hello there!") }) handler := cors.Handler(mux) http.ListenAndServe(":8080", handler) }
在示例中,我们使用 github.com/rs/cors
为我们的服务器实现 CORS 策略。我们启用了两种方法:GET 和 POST。使用 *,我们允许所有来源。
Echo CORS 示例
Go Web 框架,如 Echo、Gin 或 Fiber,都具有可立即使用的中间件,可以启用 CORS 策略。
package main import ( "net/http" "github.com/labstack/echo/v4" "github.com/labstack/echo/v4/middleware" ) var ( words = []string{"kind", "warm", "cup", "coin", "blue"} ) func getWords(c echo.Context) error { return c.JSON(http.StatusOK, words) } func main() { e := echo.New() e.Use(middleware.CORSWithConfig(middleware.CORSConfig{ AllowMethods: []string{http.MethodGet, http.MethodPost, http.MethodDelete}, })) e.GET("/api/words", getWords) e.Logger.Fatal(e.Start(":8080")) }
该示例在 Echo 框架中使用 CORS 中间件。
来源
在本文中,我们已在 Go 中处理了 CORS。