在本文中,我们定义了CORS并展示了如何在Golang中使用CORS。
$ go version go version go1.18.1 linux/amd64
我们使用Go版本1.18。
同源政策
浏览器强制执行同源策略,该策略允许网页中的JS脚本访问其他网页中的数据,前提是两个网页都具有相同的来源。origin被定义为URL方案、主机名和端口号的组合。该策略有助于隔离潜在的恶意文档,减少可能的攻击媒介。
CORS
跨源资源共享(CORS)是一种基于HTTP标头的过程,它定义允许浏览器从哪些源加载资源。
CORS通过使用HTTPCORS标头放宽了同源策略。
请求标头:
- 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
GoCORS简单示例
在以下示例中,我们在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 = 'http://localhost: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网页中,我们使用JSFetchAPI来创建GET请求。该脚本读取响应并将其设置到输出div元素中。要尝试该示例,请通过网络服务器(例如nginx)或使用实时服务器VS代码扩展加载此网页。
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))
该应用程序在本地主机上的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脚本可以访问我们的资源。
转到CORS处理程序
github.com/rs/cors是一个第三方包,它定义了在Golang中实现跨源资源共享W3规范的net/http处理程序。
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为我们的服务器实现CORSpolicy。我们启用两种方法:GET和POST。使用*,我们允许allorigins。
EchoCORS示例
Echo、Gin或Fiber等Go网络框架具有支持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。
列出所有Go教程。
