
深入了解 Gateway API 的推理擴(kuò)展
在上面的代碼片段中,我們導(dǎo)入了必要的包,包括github.com/golang-jwt/jwt/v5
。我們使用函數(shù)創(chuàng)建一個(gè)新的 JWT 令牌jwt.NewWithClaims()
。我們將簽名方法指定為HS256
以及相關(guān)信息,例如用戶名和令牌過期時(shí)間。然后,我們使用密鑰對(duì)令牌進(jìn)行簽名,并將生成的令牌作為字符串返回。
一旦我們有了令牌,我們就需要在授予對(duì)受保護(hù)資源的訪問權(quán)限之前驗(yàn)證其真實(shí)性。讓我們創(chuàng)造驗(yàn)證并解析 JWT 令牌的函數(shù):
func verifyToken (tokenString string ) error {
token, err := jwt.Parse(tokenString, func (token *jwt.Token) ( interface {}, error ) {
return secretKey, nil
})
if err != nil {
return err
}
if !token.Valid {
return fmt.Errorf( "invalid token" )
}
return nil
}
在上面的代碼片段中,我們使用jwt.Parse()
函數(shù)來解析和驗(yàn)證令牌。我們提供了一個(gè)回調(diào)函數(shù)來檢索用于簽署令牌的密鑰。如果令牌有效,我們將繼續(xù)處理請(qǐng)求;否則,我們返回一個(gè)錯(cuò)誤,表明令牌無(wú)效。
為了保護(hù)受保護(hù)的路由,我們需要引入一個(gè)登錄系統(tǒng),用戶可以在其中進(jìn)行身份驗(yàn)證并獲取 JWT 令牌。讓我們創(chuàng)建一個(gè)登錄端點(diǎn),用戶可以在其中提供他們的用戶名和密碼:
func LoginHandler (w http.ResponseWriter, r *http.Request) {
w.Header().Set( "Content-Type" , "application/json" )
var u User
json.NewDecoder(r.Body).Decode(&u)
fmt.Printf( "用戶請(qǐng)求值 %v" , u)
if u.Username == "Chek" && u.Password == "123456" {
tokenString, err := CreateToken(u.Username)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
fmt.Errorf( "未找到用戶名" )
}
w.WriteHeader(http.StatusOK)
fmt.Fprint(w, tokenString)
return
} else {
w.WriteHeader(http.StatusUnauthorized)
fmt.Fprint(w, "無(wú)效憑據(jù)" )
}
}
在上面的代碼片段中,我們定義了一個(gè)端點(diǎn),該端點(diǎn)接受請(qǐng)求主體中包含和/login
的 POST 請(qǐng)求。我們通過檢查提供的憑據(jù)是否與預(yù)期值匹配來模擬用戶身份驗(yàn)證。如果憑據(jù)有效,我們將使用該函數(shù)生成 JWT 令牌并將其作為響應(yīng)返回。否則,我們返回適當(dāng)?shù)腻e(cuò)誤響應(yīng)。username
password
createToken()
現(xiàn)在我們已經(jīng)實(shí)現(xiàn)了登錄系統(tǒng)并獲得了 JWT 令牌,讓我們修改受保護(hù)的路由以要求有效的 JWT 令牌進(jìn)行訪問:
func ProtectedHandler (w http.ResponseWriter, r *http.Request) {
w.Header().Set( "Content-Type" , "application/json" )
tokenString := r.Header.Get( "Authorization" )
if tokenString == "" {
w.WriteHeader(http.StatusUnauthorized)
fmt.Fprint(w, "Missing authorization header" )
return
}
tokenString = tokenString[ len ( "Bearer " ):]
err := verifyToken(tokenString)
if err != nil {
w.WriteHeader(http.StatusUnauthorized)
fmt.Fprint(w, "Invalid token" )
return
}
fmt.Fprint(w, "Welcome to the protected area" )
}
在上面的代碼片段中,我們檢查Authorization
請(qǐng)求標(biāo)頭中是否存在有效的 JWT 令牌。如果令牌缺失或無(wú)效,我們將返回適當(dāng)?shù)腻e(cuò)誤響應(yīng)。否則,我們將繼續(xù)提供受保護(hù)的資源。
以下是完整代碼
包主導(dǎo)
入(
“fmt”
“github.com/gorilla/mux”
“github.com/golang-jwt/jwt”
“net/http”
“encoding/json”
“time”
)
var secretKey = [] byte(“secret-key”)
func main () {
router:= mux.NewRouter()
router.HandleFunc(“/login”,login.LoginHandler)。方法(“POST”)
router.HandleFunc(“/protected”,login.ProtectedHandler)。方法(“GET”)
fmt.Println(“啟動(dòng)服務(wù)器”)
err:= http.ListenAndServe(“l(fā)ocalhost:4000”,router)
if err!= nil {
fmt.Println(“無(wú)法啟動(dòng)服務(wù)器”,err)
}
}
func LoginHandler (w http.ResponseWriter,r *http.Request) {
w.Header().Set( "Content-Type" , "application/json" )
var u User
json.NewDecoder(r.Body).Decode(&u)
fmt.Printf( "用戶請(qǐng)求值 %v" , u)
if u.Username == "Chek" && u.Password == "123456" {
tokenString, err := CreateToken(u.Username)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
fmt.Errorf( "未找到用戶名" )
}
w.WriteHeader(http.StatusOK)
fmt.Fprint(w, tokenString)
return
} else {
w.WriteHeader(http.StatusUnauthorized)
fmt.Fprint(w, "無(wú)效憑據(jù)" )
}
}
func ProtectedHandler (w http.ResponseWriter, r *http.Request) {
w.Header().Set( "Content-Type" , "application/json" )
tokenString := r.Header.Get( "Authorization" )
如果tokenString == "" {
w.WriteHeader(http.StatusUnauthorized)
fmt.Fprint(w,“缺少授權(quán)標(biāo)頭”)
返回
}
tokenString = tokenString [ len(“Bearer”:]
err:= verifyToken(tokenString)
如果err!= nil{
w.WriteHeader(http.StatusUnauthorized)
fmt.Fprint(w, "無(wú)效的令牌" )
return
}
fmt.Fprint(w, "歡迎來到保護(hù)區(qū)" )
}
func createToken (username string ) ( string , error ) {
token := jwt.NewWithClaims(jwt.SigningMethodHS256,
jwt.MapClaims{
"username" : username,
"exp" : time.Now().Add(time.Hour * 24 ).Unix(),
})
tokenString, err := token.SignedString(secretKey)
if err != nil {
return "" , err
}
return tokenString, nil
}
func verifyToken (tokenString string ) error {
token, err := jwt.Parse(tokenString, func (token *jwt.Token) ( interface {},錯(cuò)誤) {
返回secretKey,nil
})
如果err != nil {
返回err
}
如果!token.Valid {
返回fmt.Errorf(“無(wú)效令牌”)
}
返回 nil
}
請(qǐng)注意,我們還使用 創(chuàng)建了一個(gè)新的 HTTP 路由器。然后,我們使用定義了和端點(diǎn)的http.NewRouter()
路由處理程序。最后,我們通過調(diào)用 啟動(dòng)了服務(wù)器。/login
/protected
router.HandleFunc()
http.ListenAndServe(":4000", router)
此設(shè)置允許/login
端點(diǎn)處理登錄過程并生成 JWT 令牌,而/protected
端點(diǎn)在授予對(duì)受保護(hù)區(qū)域的訪問權(quán)限之前驗(yàn)證 JWT 令牌。
我們可以使用Postman測(cè)試我們的應(yīng)用程序,通過向登錄端點(diǎn)發(fā)送 Post 請(qǐng)求http://localhost:4000/login
,并使用我們的用戶名和密碼作為請(qǐng)求正文。
發(fā)布請(qǐng)求
響應(yīng)主體返回一個(gè) JWT 令牌eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2OTA4NzA2MjksInVzZXJuYW1lIjoiQ2hlayJ9.oPHtaTaIKwSuetkYpVwLMkKnCI-c9aGEKS5vFDBFl2Y。
我們現(xiàn)在發(fā)送一個(gè) GET 請(qǐng)求,并在授權(quán)標(biāo)頭中設(shè)置上述 JWT 令牌,以http://localhost:4000/protected
訪問受保護(hù)區(qū)域。
在本文中,我們探討了如何在 Golang 中實(shí)現(xiàn) JWT 令牌身份驗(yàn)證。我們學(xué)習(xí)了如何創(chuàng)建和簽署 JWT 令牌、驗(yàn)證其真實(shí)性以及構(gòu)建登錄系統(tǒng)以保護(hù)受保護(hù)的路由。通過將 JWT 令牌身份驗(yàn)證集成到您的 Go 應(yīng)用程序中,您可以增強(qiáng)安全性并實(shí)現(xiàn)無(wú)狀態(tài)身份驗(yàn)證機(jī)制。
深入了解 Gateway API 的推理擴(kuò)展
國(guó)產(chǎn)頂流AI大模型:比喻文案生成能力效果對(duì)比
Claude API 能使用 OpenAI 接口協(xié)議嗎?
天貓商品數(shù)據(jù)爬取方案:官方API與非官方接口實(shí)戰(zhàn)
地圖開發(fā)者平臺(tái)對(duì)比:高德、百度、騰訊、必應(yīng)、天地圖等API
讓大模型“聯(lián)網(wǎng)”的第一步?手把手教你調(diào)用搜索API!
API接口安全—webservice、Swagger、WEBpack
從零開始認(rèn)識(shí) API,讓網(wǎng)頁(yè)信息成為你的「知識(shí)庫(kù)」
APISIX-MCP:利用 AI + MCP 擁抱 API 智能化管理
對(duì)比大模型API的內(nèi)容創(chuàng)意新穎性、情感共鳴力、商業(yè)轉(zhuǎn)化潛力
一鍵對(duì)比試用API 限時(shí)免費(fèi)