Go JWT 鉴权中间件:用 golang-jwt 签发校验并注入上下文
test12026-10-222 次阅读
签发 token:claims 里放最小必要信息
用 github.com/golang-jwt/jwt/v5 签发,密钥从配置读、不要硬编码。claims 里只放用户标识与过期时间,敏感字段不要塞进 token。
package auth
import (
"time"
"github.com/golang-jwt/jwt/v5"
)
var secret = []byte("change-me-in-config")
type claims struct {
UserID int64 `json:"uid"`
jwt.RegisteredClaims
}
func SignToken(userID int64) (string, error) {
c := claims{
UserID: userID,
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(2 * time.Hour)),
IssuedAt: jwt.NewNumericDate(time.Now()),
},
}
return jwt.NewWithClaims(jwt.SigningMethodHS256, c).SignedString(secret)
}中间件校验并注入 context
在中间件里解析 token,失败直接 401;成功把 userID 写进 request context,下游 handler 用同一个 key 取,不靠全局变量。
package auth
import (
"context"
"net/http"
"strings"
"github.com/golang-jwt/jwt/v5"
)
type ctxKey struct{}
func Middleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
h := r.Header.Get("Authorization")
if !strings.HasPrefix(h, "Bearer ") {
http.Error(w, "missing token", http.StatusUnauthorized)
return
}
tok, err := jwt.ParseWithClaims(strings.TrimPrefix(h, "Bearer "),
&claims{}, func(t *jwt.Token) (interface{}, error) { return secret, nil })
if err != nil || !tok.Valid {
http.Error(w, "invalid token", http.StatusUnauthorized)
return
}
uid := tok.Claims.(*claims).UserID
ctx := context.WithValue(r.Context(), ctxKey{}, uid)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
func UserID(r *http.Request) int64 {
return r.Context().Value(ctxKey{}).(int64)
}读取 claims
func Profile(w http.ResponseWriter, r *http.Request) {
uid := auth.UserID(r)
fmt.Fprintf(w, "user %d", uid)
}关键结论
- 密钥走配置,token 只带最小必要字段。
- 解析失败统一 401,不要泄露具体原因。
- 身份通过 context 传递,handler 内取用,避免全局状态。
T
test1
文章作者
签发 token:claims 里放最小必要信息 用 github.com/golang-jwt/jwt/v5 签发,密...
- 分类
- 技术
- 发布时间
- 2026-10-22
- 字数
- 约 1949 字
- 阅读
- 2 次
