Golang中如何使用Token处理Mux API

Golang中如何使用Token处理Mux API 我正在使用mux编写API,并希望为我的API使用令牌。该怎么做?

8 回复

谢谢

更多关于Golang中如何使用Token处理Mux API的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


我想使用一个bar token

这是哪种类型的令牌,JWT?还是其他类型?

我在查看一个关于API身份验证的旧教程……我认为JWT是目前最常用的方法。Bearer令牌只是一个在请求体中发送的生成令牌,但这不够安全。

我从未听说过这个。什么是"bar token"?你能提供一些相关信息的链接吗?你所说的"使用"它是什么意思?这种令牌是否包含认证信息?还是其他什么?

虽然这并非您问题的确切答案,但我刚发布的一篇文章确实展示了如何在OAuth2头部使用会话令牌进行API身份验证——https://www.calhoun.io/apis-are-just-web-applications

我建议首先阅读关于JWT的内容。然后查看jwt-go库。我写了一个简短示例,说明了我如何使用这个库生成和验证JWT。

只有在您理解了JWT的基本原理以及它是如何生成和验证的之后,才应该考虑如何将其集成到HTTP服务中。

在Golang中使用mux构建API时,可以通过中间件实现令牌验证。以下是一个完整的示例,展示如何创建JWT令牌验证中间件:

package main

import (
    "context"
    "encoding/json"
    "fmt"
    "log"
    "net/http"
    "strings"
    "time"

    "github.com/dgrijalva/jwt-go"
    "github.com/gorilla/mux"
)

// 定义JWT声明结构
type Claims struct {
    Username string `json:"username"`
    jwt.StandardClaims
}

// JWT密钥
var jwtKey = []byte("your-secret-key")

// 生成JWT令牌
func generateToken(username string) (string, error) {
    expirationTime := time.Now().Add(24 * time.Hour)
    claims := &Claims{
        Username: username,
        StandardClaims: jwt.StandardClaims{
            ExpiresAt: expirationTime.Unix(),
        },
    }

    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
    return token.SignedString(jwtKey)
}

// JWT验证中间件
func authMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        authHeader := r.Header.Get("Authorization")
        if authHeader == "" {
            http.Error(w, "Authorization header required", http.StatusUnauthorized)
            return
        }

        // 检查Bearer令牌格式
        bearerToken := strings.Split(authHeader, " ")
        if len(bearerToken) != 2 || bearerToken[0] != "Bearer" {
            http.Error(w, "Invalid token format", http.StatusUnauthorized)
            return
        }

        tokenString := bearerToken[1]
        claims := &Claims{}

        token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
            return jwtKey, nil
        })

        if err != nil || !token.Valid {
            http.Error(w, "Invalid token", http.StatusUnauthorized)
            return
        }

        // 将用户信息添加到上下文
        ctx := context.WithValue(r.Context(), "username", claims.Username)
        next.ServeHTTP(w, r.WithContext(ctx))
    })
}

// 受保护的路由处理函数
func protectedHandler(w http.ResponseWriter, r *http.Request) {
    username := r.Context().Value("username").(string)
    response := map[string]string{
        "message": fmt.Sprintf("Hello %s, you have access to protected resource", username),
    }
    json.NewEncoder(w).Encode(response)
}

// 登录处理函数
func loginHandler(w http.ResponseWriter, r *http.Request) {
    var credentials struct {
        Username string `json:"username"`
        Password string `json:"password"`
    }

    if err := json.NewDecoder(r.Body).Decode(&credentials); err != nil {
        http.Error(w, "Invalid request", http.StatusBadRequest)
        return
    }

    // 简单的用户验证(生产环境应使用数据库验证)
    if credentials.Username == "admin" && credentials.Password == "password" {
        token, err := generateToken(credentials.Username)
        if err != nil {
            http.Error(w, "Error generating token", http.StatusInternalServerError)
            return
        }

        response := map[string]string{
            "token": token,
        }
        json.NewEncoder(w).Encode(response)
    } else {
        http.Error(w, "Invalid credentials", http.StatusUnauthorized)
    }
}

func main() {
    r := mux.NewRouter()

    // 公开路由
    r.HandleFunc("/login", loginHandler).Methods("POST")

    // 受保护的路由
    protected := r.PathPrefix("/api").Subrouter()
    protected.Use(authMiddleware)
    protected.HandleFunc("/protected", protectedHandler).Methods("GET")

    fmt.Println("Server running on :8080")
    log.Fatal(http.ListenAndServe(":8080", r))
}

这个示例包含以下关键部分:

  1. JWT令牌生成generateToken函数创建包含用户名的JWT令牌
  2. 认证中间件authMiddleware验证请求中的Bearer令牌
  3. 路由保护:使用mux的SubrouterUse方法应用中间件

使用示例:

# 获取令牌
curl -X POST -H "Content-Type: application/json" -d '{"username":"admin","password":"password"}' http://localhost:8080/login

# 访问受保护的路由
curl -H "Authorization: Bearer YOUR_TOKEN_HERE" http://localhost:8080/api/protected

对于简单的API密钥验证,可以使用更简单的中间件:

func apiKeyMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        apiKey := r.Header.Get("X-API-Key")
        if apiKey != "your-api-key-here" {
            http.Error(w, "Invalid API key", http.StatusUnauthorized)
            return
        }
        next.ServeHTTP(w, r)
    })
}

这种实现提供了基于令牌的API认证机制,可以根据具体需求调整令牌验证逻辑和密钥管理策略。

回到顶部