新聞中心
允許接口跨域往往是需要結(jié)合 路由管理-中間件/攔截器 一起使用,來統(tǒng)一設(shè)置某些路由規(guī)則下的接口可以跨域訪問。同時,針對允許?WebSocket?的跨域請求訪問,也是通過該方式來實現(xiàn)。

相關(guān)方法: https://pkg.GO.dev/github.com/gogf/gf/v2/net/ghttp#Response
func (r *Response) CORS(options CORSOptions)
func (r *Response) CORSAllowedOrigin(options CORSOptions) bool
func (r *Response) CORSDefault()
func (r *Response) DefaultCORSOptions() CORSOptionsCORS對象
?CORS?是?W3?互聯(lián)網(wǎng)標(biāo)準(zhǔn)組織對?HTTP?跨域請求的標(biāo)準(zhǔn),在?ghttp?模塊中,我們可以通過?CORSOptions?對象來管理對應(yīng)的跨域請求選項。定義如下:
// See https://www.w3.org/TR/cors/ .
// 服務(wù)端允許跨域請求選項
type CORSOptions struct {
AllowDomain []string // Used for allowing requests from custom domains
AllowOrigin string // Access-Control-Allow-Origin
AllowCredentials string // Access-Control-Allow-Credentials
ExposeHeaders string // Access-Control-Expose-Headers
MaxAge int // Access-Control-Max-Age
AllowMethods string // Access-Control-Allow-Methods
AllowHeaders string // Access-Control-Allow-Headers
}具體參數(shù)的介紹請查看W3組織 官網(wǎng)手冊。
CORS配置
默認CORSOptions
當(dāng)然,為方便跨域設(shè)置,在?ghttp?模塊中也提供了默認的跨域請求選項,通過?DefaultCORSOptions?方法獲取。大多數(shù)情況下,我們在需要允許跨域請求的接口中(一般情況下使用中間件)可以直接使用?CORSDefault()?允許該接口跨域訪問。
限制Origin來源
大多數(shù)時候,我們需要限制請求來源為我們受信任的域名列表,我們可以使用?AllowDomain?配置,使用方式:
// 允許跨域請求中間件
func Middleware(r *ghttp.Request) {
corsOptions := r.Response.DefaultCORSOptions()
corsOptions.AllowDomain = []string{"GoFrame.org", "johng.cn"}
r.Response.CORS(corsOptions)
r.Middleware.Next()
}OPTIONS請求
有的客戶端,部分瀏覽器在發(fā)送?AJAX?請求之前會首先發(fā)送?OPTIONS?預(yù)請求檢測后續(xù)請求是否允許發(fā)送。?GF?框架的?Server?完全遵守?W3C?關(guān)于?OPTIONS?請求方法的規(guī)范約定,因此只要服務(wù)端設(shè)置好?CORS?中間件,?OPTIONS?請求也將會自動支持。
示例1,基本使用
我們來看一個簡單的接口示例:
package main
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
)
func Order(r *ghttp.Request) {
r.Response.Write("GET")
}
func main() {
s := g.Server()
s.Group("/api.v1", func(group *ghttp.RouterGroup) {
group.GET("/order", Order)
})
s.SetPort(8199)
s.Run()
}接口地址是 http://localhost/api.v1/order ,當(dāng)然這個接口是不允許跨域的。我們打開一個不同的域名,例如:百度首頁(正好用了?jQuery?,方便調(diào)試),然后按?F12?打開開發(fā)者面板,在?console?下執(zhí)行以下?AJAX?請求:
$.get("http://localhost:8199/api.v1/order", function(result){
console.log(result)
});結(jié)果如下:
返回了不允許跨域請求的提示錯誤,接著我們修改一下服務(wù)端接口的測試代碼,如下:
package main
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
)
func MiddlewareCORS(r *ghttp.Request) {
r.Response.CORSDefault()
r.Middleware.Next()
}
func Order(r *ghttp.Request) {
r.Response.Write("GET")
}
func main() {
s := g.Server()
s.Group("/api.v1", func(group *ghttp.RouterGroup) {
group.Middleware(MiddlewareCORS)
group.GET("/order", Order)
})
s.SetPort(8199)
s.Run()
}我們增加了針對于路由?/api.v1?的前置中間件?MiddlewareCORS?,該事件將會在所有服務(wù)執(zhí)行之前調(diào)用。我們通過調(diào)用?CORSDefault?方法使用默認的跨域設(shè)置允許跨域請求。該綁定的事件路由規(guī)則使用了模糊匹配規(guī)則,表示所有?/api.v1?開頭的接口地址都允許跨域請求。
返回剛才的百度首頁,再次執(zhí)行請求?AJAX?請求,這次便成功了:
當(dāng)然我們也可以通過?CORSOptions?對象以及?CORS?方法對跨域請求做更多的設(shè)置。
示例2,授權(quán)跨域Origin
在大多數(shù)場景中,我們是需要自定義授權(quán)跨域的?Origin?,那么我們可以將以上的例子改進如下,在該示例中,我們僅允許?goframe.org?及?baidu.com?跨域請求訪問。
package main
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
)
func MiddlewareCORS(r *ghttp.Request) {
corsOptions := r.Response.DefaultCORSOptions()
corsOptions.AllowDomain = []string{"goframe.org", "baidu.com"}
r.Response.CORS(corsOptions)
r.Middleware.Next()
}
func Order(r *ghttp.Request) {
r.Response.Write("GET")
}
func main() {
s := g.Server()
s.Group("/api.v1", func(group *ghttp.RouterGroup) {
group.Middleware(MiddlewareCORS)
group.GET("/order", Order)
})
s.SetPort(8199)
s.Run()
}示例3,自定義檢測授權(quán)
不知大家是否有注意,在以上的示例中有個細節(jié),即使當(dāng)前接口不允許跨域訪問,但是只要接口被調(diào)用,接口完整邏輯仍會被執(zhí)行,在服務(wù)端其實也已經(jīng)走完了一次請求流程。針對于這個問題,我們可以通過自定義授權(quán)?Origin?并在中間件中通過?CORSAllowedOrigin?方法來做判斷,如果當(dāng)前請求的?Origin?在服務(wù)端是被允許執(zhí)行的,那么才會執(zhí)行后續(xù)流程,否則便會終止執(zhí)行。
在以下示例中,僅允許來自?goframe.org?域名的跨域請求,而來自其他域名的請求將會失敗并返回?403?:
package main
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
)
func MiddlewareCORS(r *ghttp.Request) {
corsOptions := r.Response.DefaultCORSOptions()
corsOptions.AllowDomain = []string{"goframe.org"}
if !r.Response.CORSAllowedOrigin(corsOptions) {
r.Response.WriteStatus(http.StatusForbidden)
return
}
r.Response.CORS(corsOptions)
r.Middleware.Next()
}
func Order(r *ghttp.Request) {
r.Response.Write("GET")
}
func main() {
s := g.Server()
s.Group("/api.v1", func(group *ghttp.RouterGroup) {
group.Middleware(MiddlewareCORS)
group.GET("/order", Order)
})
s.SetPort(8199)
s.Run()
} 分享名稱:創(chuàng)新互聯(lián)GoFrame教程:GoFrame 高級特性-CORS跨域處理
標(biāo)題URL:http://m.fisionsoft.com.cn/article/cooidjh.html


咨詢
建站咨詢
