Go語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單JWT登錄驗(yàn)證的示例代碼
在 Web 開發(fā)中,身份驗(yàn)證是一個(gè)繞不開的話題。傳統(tǒng)的 Session 機(jī)制依賴服務(wù)器存儲(chǔ)用戶狀態(tài),而在微服務(wù)、分布式架構(gòu)下,這種方式可能會(huì)導(dǎo)致狀態(tài)同步困難。
JWT(JSON Web Token)是一種無狀態(tài)的、跨平臺(tái)的身份驗(yàn)證解決方案,非常適合現(xiàn)代 Web API 場(chǎng)景。
本文將帶你用 Go 實(shí)現(xiàn)一個(gè) JWT 登錄驗(yàn)證示例,掌握它的基本原理與使用方式。
一、什么是 JWT
JWT 的結(jié)構(gòu)由三部分組成:
header.payload.signature
- • Header:聲明類型(JWT)和加密算法(如 HMAC SHA256)。
- • Payload:存放業(yè)務(wù)數(shù)據(jù)(如用戶ID、角色、過期時(shí)間)。
- • Signature:對(duì)前兩部分進(jìn)行簽名,保證數(shù)據(jù)不可篡改。
例如:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.eyJ1c2VyX2lkIjoxLCJleHAiOjE3MDAwMDAwMDB9
.abc123456789xyz
二、實(shí)現(xiàn)思路
1. 用戶登錄 → 校驗(yàn)賬號(hào)密碼正確 → 生成 JWT 返回給前端。
2. 前端請(qǐng)求 API → 在 Authorization 頭中攜帶 JWT。
3. 后端中間件 → 解析 JWT,驗(yàn)證有效性與過期時(shí)間。
4. 通過驗(yàn)證 → 執(zhí)行后續(xù)業(yè)務(wù)邏輯。
三、代碼實(shí)現(xiàn)
我們使用 github.com/golang-jwt/jwt/v5 作為 JWT 庫(kù)。
1. 初始化依賴
go get github.com/golang-jwt/jwt/v5
2. 定義 JWT 工具
package main
import (
"fmt"
"time"
"github.com/golang-jwt/jwt/v5"
)
var jwtSecret = []byte("my_secret_key")
// 生成Token
func GenerateToken(username string) (string, error) {
claims := jwt.MapClaims{
"username": username,
"exp": time.Now().Add(2 * time.Hour).Unix(),
"iat": time.Now().Unix(),
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString(jwtSecret)
}
// 驗(yàn)證Token
func ParseToken(tokenString string) (jwt.MapClaims, error) {
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
return jwtSecret, nil
})
if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
return claims, nil
}
return nil, err
}
3. 構(gòu)建簡(jiǎn)單登錄和受保護(hù)接口
package main
import (
"encoding/json"
"fmt"
"net/http"
"strings"
)
// 模擬用戶數(shù)據(jù)
var users = map[string]string{
"alice": "123456",
"bob": "654321",
}
func loginHandler(w http.ResponseWriter, r *http.Request) {
username := r.FormValue("username")
password := r.FormValue("password")
if pwd, ok := users[username]; !ok || pwd != password {
http.Error(w, "用戶名或密碼錯(cuò)誤", http.StatusUnauthorized)
return
}
token, _ := GenerateToken(username)
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]string{"token": token})
}
func authMiddleware(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
authHeader := r.Header.Get("Authorization")
if authHeader == "" {
http.Error(w, "缺少Authorization頭", http.StatusUnauthorized)
return
}
parts := strings.SplitN(authHeader, " ", 2)
if len(parts) != 2 || parts[0] != "Bearer" {
http.Error(w, "Authorization格式錯(cuò)誤", http.StatusUnauthorized)
return
}
claims, err := ParseToken(parts[1])
if err != nil {
http.Error(w, "無效Token", http.StatusUnauthorized)
return
}
fmt.Printf("JWT解析結(jié)果: %+v\n", claims)
next.ServeHTTP(w, r)
}
}
func protectedHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "歡迎訪問受保護(hù)的資源!")
}
func main() {
http.HandleFunc("/login", loginHandler)
http.HandleFunc("/protected", authMiddleware(protectedHandler))
fmt.Println("服務(wù)器啟動(dòng):http://localhost:8080")
http.ListenAndServe(":8080", nil)
}
4. 測(cè)試流程
1. 登錄獲取 Token
curl -X POST "http://localhost:8080/login" -d "username=alice&password=123456"
返回:
{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI..."}
2. 訪問受保護(hù)接口
curl -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI..." http://localhost:8080/protected
輸出:
歡迎訪問受保護(hù)的資源!
四、注意事項(xiàng)
1. Token 過期處理:前端需在過期后重新獲取 Token。
2. Secret 安全性:切勿將 jwtSecret 寫死在代碼里,可用環(huán)境變量管理。
3. HTTPS:避免 Token 在明文傳輸中被竊取。
4. 黑名單機(jī)制:如果需要即時(shí)讓某個(gè) Token 失效,可以維護(hù)一個(gè)黑名單。
五、總結(jié)
JWT 在 Go 中實(shí)現(xiàn)并不復(fù)雜,但它帶來的無狀態(tài)身份驗(yàn)證機(jī)制,非常適合 RESTful API 和分布式架構(gòu)場(chǎng)景。
通過本示例,你可以快速搭建一個(gè)基于 JWT 的登錄驗(yàn)證系統(tǒng),并根據(jù)業(yè)務(wù)需求進(jìn)行擴(kuò)展,比如刷新 Token、角色權(quán)限控制等。
到此這篇關(guān)于Go語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單JWT登錄驗(yàn)證的示例代碼的文章就介紹到這了,更多相關(guān)Go JWT登錄驗(yàn)證內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go語(yǔ)言實(shí)現(xiàn)本地緩存的策略詳解
今天給大家分享的是Go語(yǔ)言本地緩存的一些內(nèi)容,主要是結(jié)合bigcache和fastcache兩個(gè)優(yōu)秀的開源代碼庫(kù),總結(jié)一些設(shè)計(jì)思路和感悟,文章通過代碼示例介紹的非常詳細(xì),需要的朋友可以參考下2023-07-07
解決goland 導(dǎo)入項(xiàng)目后import里的包報(bào)紅問題
這篇文章主要介紹了解決goland 導(dǎo)入項(xiàng)目后import里的包報(bào)紅問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-05-05
使用Golang的singleflight防止緩存擊穿的方法
這篇文章主要介紹了使用Golang的singleflight防止緩存擊穿的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04
Go語(yǔ)言內(nèi)建函數(shù)cap的實(shí)現(xiàn)示例
cap 是一個(gè)常用的內(nèi)建函數(shù),它用于獲取某些數(shù)據(jù)結(jié)構(gòu)的容量,本文主要介紹了Go語(yǔ)言內(nèi)建函數(shù)cap的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下2024-08-08
golang Goroutine超時(shí)控制的實(shí)現(xiàn)
日常開發(fā)中我們大概率會(huì)遇到超時(shí)控制的場(chǎng)景,比如一個(gè)批量耗時(shí)任務(wù)、網(wǎng)絡(luò)請(qǐng)求等,本文主要介紹了golang Goroutine超時(shí)控制的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-09-09

