安全的關(guān)鍵.png)
ASP.NET Web API快速入門介紹
<head>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
</head>
<body>
<script>
$(document).ready(function(){
const url = "http://127.0.0.1:8080/api/v1/test";
$.ajax({
url: url,
type: "GET",
success:function(result){
console.log(result)
},
error:function(error){
console.log(error)
}
})
})
</script>
</body>
</html>
這時(shí)如果在瀏覽器中打開(kāi)這個(gè)文件,或者使用nginx作為靜態(tài)代理,只要該文件「不是」通過(guò)http://127.0.0.1:8080
這個(gè)域發(fā)起的請(qǐng)求,則由于瀏覽器的同源策略都會(huì)被攔截。
Access to XMLHttpRequest at 'http://127.0.0.1:8080/api/v1/test' from origin 'http://127.0.0.1:8888' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
瀏覽器在發(fā)送http請(qǐng)求的時(shí)候,會(huì)在header中記錄Origin信息
我們先來(lái)看下gin是如何獲取請(qǐng)求 header 信息的,gin 通過(guò) *gin.Context.Request.Header
來(lái)獲取到請(qǐng)求頭信息
func (ApiV1) Get(c *gin.Context) {
fmt.Println(c.Request.Header)
c.JSON(200, gin.H{"msg": "handlers get request!"})
}
想要獲取到Origin
信息,Header 本身是個(gè) map[string][]string
類型數(shù)據(jù),可能通過(guò)Get方法來(lái)獲取Origin信息
在響應(yīng)頭中將該域添加到 Access-Control-Allow-Origin
中,并同時(shí)設(shè)置 Access-Control-Allow-Methods
func (ApiV1) Get(c *gin.Context) {
origin := c.Request.Header.Get("Origin") //請(qǐng)求頭部
if origin!=""{
// 將該域添加到allow-origin中
c.Header("Access-Control-Allow-Origin", origin) //
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE")
c.Header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization")
c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Cache-Control, Content-Language, Content-Type")
//允許客戶端傳遞校驗(yàn)信息比如 cookie
c.Header("Access-Control-Allow-Credentials", "true")
}
c.JSON(200, gin.H{"msg": "handlers get request!"})
}
這時(shí)再訪問(wèn)剛才的html文件就可以正常的請(qǐng)求到了數(shù)據(jù)。
寫成中間件
上面只是針對(duì)某一個(gè)接口,如果想要所有的接口都可以被跨域請(qǐng)求,則可以將其寫成一個(gè)中間件,上面是將所有的域都允許跨域請(qǐng)求,其實(shí)還是有點(diǎn)問(wèn)題的,這里我將允許跨域請(qǐng)求的地址寫到一個(gè)map中,本來(lái)想寫到數(shù)組或者slice中,但是發(fā)現(xiàn)在判斷是否存在的時(shí)候,golang中并沒(méi)有in 運(yùn)算符,需要遍歷數(shù)組或者slice,復(fù)雜度為O(n) ,還是使用map吧。
另外如果請(qǐng)求方法是OPTIONS
的話,如websocket請(qǐng)求會(huì)先發(fā)一個(gè)OPTIONS請(qǐng)求,這時(shí)可以不進(jìn)行校驗(yàn),直接返回
package midwares
import (
"github.com/gin-gonic/gin"
)
func CheckCors() gin.HandlerFunc {
//這里可以處理一些別的邏輯
return func(c *gin.Context) {
// 定義一個(gè)origin的map,只有在字典中的key才允許跨域請(qǐng)求
var allowOrigins = map[string]struct{}{
"http://127.0.0.1:8888": struct {}{},
"https://www.yangyanxing.com": struct {}{},
}
origin := c.Request.Header.Get("Origin") //請(qǐng)求頭部
method := c.Request.Method
if method == "OPTIONS"{
c.AbortWithStatus(http.StatusNoContent)
}
if origin!=""{
if _, ok:=allowOrigins[origin];ok{
c.Header("Access-Control-Allow-Origin", origin)
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE")
c.Header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization")
c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Cache-Control, Content-Language, Content-Type")
c.Header("Access-Control-Allow-Credentials", "true")
}
}
c.Next()
}
}
在main.go中加入該中間件
func main() {
r := gin.Default()
r.Use(midwares.CheckCors())
....
r.Run(":8080")
之后就可以完成跨域請(qǐng)求了。
文章轉(zhuǎn)自微信公眾號(hào)@序語(yǔ)程言
ASP.NET Web API快速入門介紹
2024年在線市場(chǎng)平臺(tái)的11大最佳支付解決方案
完整指南:如何在應(yīng)用程序中集成和使用ChatGPT API
選擇AI API的指南:ChatGPT、Gemini或Claude,哪一個(gè)最適合你?
用ASP.NET Core 2.1 建立規(guī)范的 REST API — 緩存和并發(fā)
企業(yè)工商數(shù)據(jù)API用哪種?
2024年創(chuàng)建社交媒體帖子的最佳圖像工具API
2024年小型企業(yè)的7個(gè)最佳短信應(yīng)用API
用gin寫簡(jiǎn)單的crud后端API接口
對(duì)比大模型API的內(nèi)容創(chuàng)意新穎性、情感共鳴力、商業(yè)轉(zhuǎn)化潛力
一鍵對(duì)比試用API 限時(shí)免費(fèi)