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。