入(
“fmt”
“github.com/golang-jwt/jwt/v5”
“time”


var secretKey = [] byte(“secret-key”)

func createToken (username字符串)(string,error){
token:= jwt.NewWithClaims(jwt.SigningMethodHS256,
jwt.MapClaims{
“username”:username,
“exp”:time.Now()。Add(time.Hour * 24).Unix(),
})

tokenString,err:= token.SignedString(secretKey)
如果err!= nil {
返回 “”,err
}

返回tokenString,nil
}

在上面的代碼片段中,我們導(dǎo)入了必要的包,包括github.com/golang-jwt/jwt/v5。我們使用函數(shù)創(chuàng)建一個(gè)新的 JWT 令牌jwt.NewWithClaims()。我們將簽名方法指定為HS256 以及相關(guān)信息,例如用戶名和令牌過期時(shí)間。然后,我們使用密鑰對(duì)令牌進(jìn)行簽名,并將生成的令牌作為字符串返回。

驗(yàn)證 JWT 令牌

一旦我們有了令牌,我們就需要在授予對(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ú)效。

實(shí)現(xiàn)登錄系統(tǒng)

為了保護(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)。usernamepasswordcreateToken()

確保受保護(hù)的路線

現(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/protectedrouter.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ū)域。

結(jié)論

在本文中,我們探討了如何在 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ī)制。

上一篇:

每個(gè) API 團(tuán)隊(duì)都應(yīng)該知道的十大 API 安全威脅

下一篇:

通過API監(jiān)控提高API穩(wěn)定性
#你可能也喜歡這些API文章!

我們有何不同?

API服務(wù)商零注冊(cè)

多API并行試用

數(shù)據(jù)驅(qū)動(dòng)選型,提升決策效率

查看全部API→
??

熱門場(chǎng)景實(shí)測(cè),選對(duì)API

#AI文本生成大模型API

對(duì)比大模型API的內(nèi)容創(chuàng)意新穎性、情感共鳴力、商業(yè)轉(zhuǎn)化潛力

25個(gè)渠道
一鍵對(duì)比試用API 限時(shí)免費(fèi)

#AI深度推理大模型API

對(duì)比大模型API的邏輯推理準(zhǔn)確性、分析深度、可視化建議合理性

10個(gè)渠道
一鍵對(duì)比試用API 限時(shí)免費(fèi)