首页  >  文章  >  后端开发  >  使用 JWT 身份验证保护您的 Go API

使用 JWT 身份验证保护您的 Go API

Susan Sarandon
Susan Sarandon原创
2024-10-03 12:07:01728浏览

Securing Your Go API with JWT Authentication

好吧,让我们说实话。安全性是一件大事,如果您正在构建 API,您不能让任何人闯入并开始弄乱您的数据。这就是 JWT(JSON Web 令牌) 发挥作用的地方。今天,我们通过添加基于 JWT 的身份验证来升级 Go API。

快速注意?

如果您一直在使用旧的 github.com/dgrijalva/jwt-go 软件包,那么是时候升级了。新标准是 github.com/golang-jwt/jwt/v4。

为什么要切换?

  • 原作者移交了控制权,新的维护者一直忙于改进和修复安全问题。
  • 从 4.0.0 版本开始,他们添加了 Go 模块支持并改进了令牌验证。
  • 如果您仍在使用旧软件包,请查看他们的 MIGRATION_GUIDE.md。

现在,让我们开始使用我们精美的新 JWT 库!

JWT 又是什么? ?

对于 JWT 新手:

  • 它就像一个用于访问您的 API 的签名许可单。
  • API 生成一个令牌,对其进行签名,然后客户端(用户、应用程序等)在每个请求中包含该令牌。
  • 服务器检查令牌并说:“是的,你是合法的。”

现在您已经熟悉了,让我们深入研究代码!


设置项目

我们将从上一篇文章中离开的地方继续。让我们更新 Go 模块并安装必要的软件包:

  1. 添加 JWT 包和 mux 路由器:
   go get github.com/golang-jwt/jwt/v4
   go get github.com/gorilla/mux
  1. 打开你的 main.go 文件,让我们开始编码!

第 1 步:生成 JWT 令牌

首先,我们将创建一个函数,在用户登录时生成 JWT 令牌。该令牌将包含用户名,并将使用密钥进行签名。

var jwtKey = []byte("my_secret_key")

type Credentials struct {
    Username string `json:"username"`
    Password string `json:"password"`
}

type Claims struct {
    Username string `json:"username"`
    jwt.RegisteredClaims
}

func generateToken(username string) (string, error) {
    expirationTime := time.Now().Add(5 * time.Minute)

    claims := &Claims{
        Username: username,
        RegisteredClaims: jwt.RegisteredClaims{
            ExpiresAt: jwt.NewNumericDate(expirationTime),
        },
    }

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

此函数生成一个令牌,该令牌将在 5 分钟后过期,并使用 HS256 算法进行签名。


第 2 步:创建登录端点

接下来,我们将构建一个登录端点,用户可以在其中发送凭据。如果登录信息检查通过,我们将生成一个 JWT 并将其通过 cookie 发回。

func login(w http.ResponseWriter, r *http.Request) {
    var creds Credentials
    err := json.NewDecoder(r.Body).Decode(&creds)
    if err != nil {
        w.WriteHeader(http.StatusBadRequest)
        return
    }

    if creds.Username != "admin" || creds.Password != "password" {
        w.WriteHeader(http.StatusUnauthorized)
        return
    }

    token, err := generateToken(creds.Username)
    if err != nil {
        w.WriteHeader(http.StatusInternalServerError)
        return
    }

    http.SetCookie(w, &http.Cookie{
        Name:    "token",
        Value:   token,
        Expires: time.Now().Add(5 * time.Minute),
    })
}

步骤 3:JWT 验证中间件

现在,我们需要一个中间件函数来验证 JWT 令牌,然后才能允许访问受保护的路由。

func authenticate(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        c, err := r.Cookie("token")
        if err != nil {
            if err == http.ErrNoCookie {
                w.WriteHeader(http.StatusUnauthorized)
                return
            }
            w.WriteHeader(http.StatusBadRequest)
            return
        }

        tokenStr := c.Value
        claims := &Claims{}

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

        if err != nil || !tkn.Valid {
            w.WriteHeader(http.StatusUnauthorized)
            return
        }

        next.ServeHTTP(w, r)
    })
}

此中间件检查请求是否具有有效的 JWT 令牌。如果不是,它会返回未经授权的响应。


步骤 4:保护路由

现在,让我们应用我们的身份验证中间件来保护 /books 路由:

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

    r.HandleFunc("/login", login).Methods("POST")
    r.Handle("/books", authenticate(http.HandlerFunc(getBooks))).Methods("GET")

    fmt.Println("Server started on port :8000")
    log.Fatal(http.ListenAndServe(":8000", r))
}

测试 API

  1. 登录生成令牌:
   curl -X POST http://localhost:8000/login -d '{"username":"admin", "password":"password"}' -H "Content-Type: application/json"
  1. 访问受保护的 /books 端点:
   curl --cookie "token=<your_token>" http://localhost:8000/books

如果令牌有效,您将获得访问权限。如果没有,您将收到“401 Unauthorized”。


接下来是什么?

下次,我们将把 API 连接到数据库来管理用户凭据和存储数据。更多精彩敬请期待!

以上是使用 JWT 身份验证保护您的 Go API的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn