package middleware import ( "context" "errors" "net/http" "strings" "github.com/golang-jwt/jwt/v4" ) const ( jwtAudience = "aud" jwtExpire = "exp" jwtId = "jti" jwtIssueAt = "iat" jwtIssuer = "iss" jwtNotBefore = "nbf" jwtSubject = "sub" noDetailReason = "no detail reason" ) type OptionalJwtMiddleware struct { Secret string } func NewOptionalJwtMiddleware(secret string) *OptionalJwtMiddleware { return &OptionalJwtMiddleware{ Secret: secret, } } func (m *OptionalJwtMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { // 尝试从请求头中获取 JWT 令牌 tokenString := r.Header.Get("Authorization") ctx := r.Context() if len(tokenString) > 0 { // 如果提供了 JWT 令牌,则验证它 tokenValue := strings.Split(tokenString, " ") if len(tokenValue) == 2 { parsedToken, err := jwt.Parse(tokenValue[1], func(token *jwt.Token) (interface{}, error) { if _, ok := token.Method.(*jwt.SigningMethodHMAC); ok { return []byte(m.Secret), nil } return nil, errors.New("failed to parse token") }) if err == nil { if claims, ok := parsedToken.Claims.(jwt.MapClaims); ok && parsedToken.Valid { // 将解析到的 claims 添加到请求上下文中 for k, v := range claims { switch k { case jwtAudience, jwtExpire, jwtId, jwtIssueAt, jwtIssuer, jwtNotBefore, jwtSubject: // ignore the standard claims default: ctx = context.WithValue(ctx, k, v) } } } } } } newReq := r.WithContext(ctx) next(w, newReq) } }