欢迎访问宙启技术站
智能推送

使用go-zero在Go中快速实现JWT认证

发布时间:2023-05-15 06:23:47

JWT(JSON Web Token)是一种用于进行认证和授权的标准化方法,通常用于 Web 应用程序中的身份验证和授权。在使用 JWT 进行身份验证时,应用程序会向用户提供一个 JWT,用户在每次请求时都将这个 JWT 发送到应用程序,以便应用程序可以通过验证 JWT 来确定用户的身份。

Go-Zero 是一款基于 Golang 的微服务开发框架,它内置了大量的开箱即用的功能,如网关、服务发现、配置中心等。Go-Zero 还提供了许多工具,如 API 代码生成器、客户端生成器等,使开发人员能够快速打造高性能、稳定、易维护的微服务应用程序。

在本文中,我们将介绍如何使用 Go-Zero 快速实现 JWT 认证。

1. 安装依赖库

首先,我们需要在项目中安装以下依赖库:

go get -u github.com/dgrijalva/jwt-go

2. 创建 JWT Middleware

在 Go-Zero 中,我们可以使用 Middleware 来实现 JWT 认证。我们可以创建一个 JWT Middleware 来处理所有需要认证的请求。首先,我们需要创建一个 JWT 配置结构体:

// JWT 配置结构体

type JWTConfig struct {

    SigningKey []byte

}

SigningKey 是 JWT 的签名密钥,我们可以在配置文件中配置。

接下来,我们需要创建一个 JWT Middleware,它负责验证 JWT 并将用户信息添加到上下文中:

// JWT Middleware

func JwtMiddleware(cfg *JWTConfig) middleware.Middleware {

    return func(next http.HandlerFunc) http.HandlerFunc {

        return func(w http.ResponseWriter, r *http.Request) {

            tokenString := r.Header.Get("Authorization")

            if tokenString == "" {

                http.Error(w, "Authorization token not found", http.StatusUnauthorized)

                return

            }

            token, err := jwt.ParseWithClaims(tokenString, &jwt.StandardClaims{}, func(token *jwt.Token) (interface{}, error) {

                if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {

                    return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])

                }

                return cfg.SigningKey, nil

            })

            if err != nil {

                http.Error(w, err.Error(), http.StatusUnauthorized)

                return

            }

            if !token.Valid {

                http.Error(w, "Invalid authorization token", http.StatusUnauthorized)

                return

            }

            claims, ok := token.Claims.(*jwt.StandardClaims)

            if !ok {

                http.Error(w, "Invalid authorization token", http.StatusUnauthorized)

                return

            }

            ctx := context.WithValue(r.Context(), "userId", claims.Subject)

            next(w, r.WithContext(ctx))

        }

    }

}

该函数接受一个 JWTConfig 结构体并返回一个 Middleware 函数。中间件函数检查 Authorization 头中是否包含 JWT。如果没有,它返回 HTTP 401 错误。如果存在,它会使用 SigningKey 进行解密。如果解密失败或 JWT 无效,则返回 HTTP 401 错误。否则,它将用户信息添加到上下文中,并将请求传递给下一个处理程序。

3. 使用 JWT Middleware

现在我们已经创建了 JWT Middleware,下一步是将它应用到需要认证的请求中。我们可以使用 Go-Zero 的 Middleware 方法将中间件添加到路由处理程序中:

// 添加 JWT Middleware 到路由

r := httpx.NewRouter()

r.GET("/api/hello", JwtMiddleware(&JWTConfig{SigningKey: []byte("signing key")})(HelloHandler))

在这里,我们将 JwtMiddleware 作为处理程序的 个参数传递给 NewRouter 方法。如果请求到达 "/api/hello" 路由路径,JwtMiddleware 将首先运行。如果认证通过,则 HelloHandler 函数将被调用。

4. 创建 JWT

现在,我们已经创建了 JWT Middleware 并将其应用到需要认证的请求中。下一步是创建 JWT 并将其提供给客户端。我们可以创建一个 JWT 生成函数,该函数为具有用户 ID 的 JWT 签名:

// JWT 生成函数

func GenerateJWT(userId string, signingKey []byte, expireTime time.Duration) (string, error) {

    claims := jwt.StandardClaims{

        ExpiresAt: time.Now().Add(expireTime).Unix(),

        Subject: userId,

    }

    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)

    tokenString, err := token.SignedString(signingKey)

    if err != nil {

        return "", err

    }

    return tokenString, nil

}

该函数接受用户 ID,签名密钥和 JWT 的过期时间,生成带有用户 ID 和过期时间的 JWT 并进行签名。然后,它将 JWT 返回给调用者。

在客户端代码中,我们可以通过调用此函数来获取 JWT 并将其发送到服务器:

jwt, err := GenerateJWT("user123", []byte("signing key"), time.Hour)

if err != nil {

    // 处理错误

}

req, err := http.NewRequest("GET", "/api/hello", nil)

if err != nil {

    // 处理错误

}

req.Header.Set("Authorization", jwt)

resp, err := http.DefaultClient.Do(req)

if err != nil {

    // 处理错误

}

// 处理响应

5. 结论

在本文中,我们介绍了如何使用 Go-Zero 快速实现 JWT 认证。我们创建了一个 JWT Middleware,该中间件检查 Authorization 头中是否包含 JWT 并验证 JWT。我们还创建了一个 JWT 生成函数,该函数为具有用户 ID 的 JWT 签名。通过使用这些函数,我们可以快速、简单地实现 JWT 认证。