OAuth 2.0 和 JWT 在 Go 中的授权:初学者完整指南

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

引言:为什么在 Go 中需要 OAuth 2.0 和 JWT?

\n

现代 Web 应用程序和 API 很少能绕过授权系统。如果您正在使用 Go (Golang) 进行开发,并希望保护您的端点,您需要了解两项关键技术:OAuth 2.0(访问委托协议)和 JWT(JSON Web Token——一种紧凑的令牌格式)。

\n

在本文中,我们将从零开始讲解如何在 Go 中实现安全授权。您将了解到:

\n
    \n
  • OAuth 2.0 与 JWT 的区别以及它们如何协同工作。
  • \n
  • 如何在 Go 中生成和验证 JWT 令牌。
  • \n
  • 如何构建一个最小的 OAuth 2.0 授权(客户端凭证流程)。
  • \n
  • 如何使用中间件保护 REST API。
  • \n
\n

本文面向已经熟悉 Go 基础和 HTTP 服务器的初级开发者。

\n\n

基础知识:OAuth 2.0 和 JWT 不是一回事

\n

许多初学者会混淆这两个概念。让我们先明确一下。

\n\n

什么是 OAuth 2.0?

\n

OAuth 2.0 是一种授权协议,它允许一个服务(客户端)代表用户获得对另一个服务(服务器)资源的有限访问权限。想象一下,您想通过 Google 登录一个网站。该网站不会获取您的密码——它会从 Google 获得一个临时令牌,该令牌仅允许访问您的电子邮件(并且需要您的同意)。

\n

OAuth 2.0 中的主要角色:

\n
    \n
  • 资源所有者 — 数据的所有者(通常是用户)。
  • \n
  • 客户端 — 想要获得访问权限的应用程序。
  • \n
  • 授权服务器 — 验证后颁发令牌的服务器。
  • \n
  • 资源服务器 — 存储受保护数据并验证令牌的服务器。
  • \n
\n\n

什么是 JWT?

\n

JWT (JSON Web Token) 是令牌本身的格式。它是由点分隔的三部分组成的字符串:header.payload.signature。JWT 可以包含任何数据(例如,用户 ID、角色、过期时间),并使用密钥签名,以防止被篡改。

\n

OAuth 2.0 不绑定 JWT——令牌可以是任何字符串。然而,在实践中,JWT 最常用,因为它是自包含的:服务器无需在数据库中存储会话,所有信息都可以即时验证。

\n\n

在 Go 中实现 JWT:令牌的生成与验证

\n

我们从实践开始。要在 Go 中使用 JWT,我们将使用 golang-jwt/jwt/v5 库。安装它:

\n
go get github.com/golang-jwt/jwt/v5
\n\n

生成访问令牌

\n

创建一个函数,该函数接收用户 ID 并返回一个签名的 JWT 令牌,有效期为 1 小时。

\n
package main\n\nimport (\n    "time"\n    "github.com/golang-jwt/jwt/v5"\n)\n\nvar jwtSecret = []byte("your-secret-key") // 在生产环境中,请存储在 .env 文件中!\n\ntype Claims struct {\n    UserID uint `json:"user_id"`\n    jwt.RegisteredClaims\n}\n\nfunc GenerateAccessToken(userID uint) (string, error) {\n    claims := Claims{\n        UserID: userID,\n        RegisteredClaims: jwt.RegisteredClaims{\n            ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour)),\n            IssuedAt:  jwt.NewNumericDate(time.Now()),\n            Issuer:    "my-app",\n        },\n    }\n    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)\n    return token.SignedString(jwtSecret)\n}
\n\n

验证和解析 JWT

\n

现在,编写一个中间件,用于验证来自 Authorization: Bearer <token> 头的令牌。

\n
func ValidateToken(tokenString string) (*Claims, error) {\n    token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) {\n        // 检查是否使用了正确的签名方法\n                

博客

书籍推荐