在Golang REST API中实现JWT身份验证

作者:API传播员 · 2026-01-08 · 阅读时间:7分钟

在本文中,我们将深入探讨如何在 Golang JSON Web Token)身份验证,并通过身份验证中间件确保其安全性。我们将构建一个结构清晰的 Golang REST API,主要使用 Gin 作为路由框架,并结合 GORM 将用户数据持久化到 MySQL 数据库中。此外,我们还会实现一个中间件,用于保护 API 端点,仅允许携带有效 JWT 的请求访问。


什么是 JWT?

在开始实现之前,我们先了解一下 JWT 的基本概念。

JWT(JSON RESTful API 用于无状态的身份验证。JWT 的结构由三部分组成:

  1. 标头(Header):包含签名算法信息,如 HMAC SHA256 或 RSA。
  2. 有效载荷(Payload):包含声明信息,例如用户名、电子邮件等。需要注意的是,敏感数据(如密码)不应包含在 JWT 中。
  3. 签名(Signature):用于验证 JWT 的完整性,确保其未被篡改。

以下是一个 JWT 的示例结构:

JWT 示例


开始实现 Golang JWT 身份验证

环境准备

在开发过程中,我们将使用以下工具和技术:

  • IDE:Visual Studio Code(VS Code),推荐安装 Golang 扩展以提升开发效率
  • Golang 版本:确保安装最新稳定版的 Golang SDK(本文撰写时为 Go 1.18.1)。
  • 数据库:MySQL,用于存储用户数据。

首先,在 VS Code 中创建一个新文件夹,并初始化 Golang 项目依赖项。接着,创建一个 main.go 文件,作为项目的入口。


项目结构概述

我们将构建一个包含以下功能的 REST API:

  1. 令牌控制器:提供生成 JWT 的端点,用户需提供有效的电子邮件和密码。
  2. 用户控制器:提供用户注册端点,用于创建新用户。
  3. 安全控制器:受 JWT 身份验证保护的端点,仅允许有效 JWT 的请求访问。

此外,我们将实现以下辅助功能:

  • 生成和验证 JWT 的工具函数。
  • 使用 GORM 将用户数据存储到 MySQL 数据库。
  • 使用 bcrypt 对用户密码进行加密和验证。

Gin 框架简介

Gin 是一个高性能的 Golang Web 框架,号称比标准 HTTP 路由器快 40 倍。它在 GitHub 上拥有超过 55,000 颗星,开发体验优秀,能够大幅减少样板代码。

运行以下命令安装 Gin:

go get -u github.com/gin-gonic/gin

数据库设置与迁移

创建用户模型

在项目中创建一个 models 文件夹,并添加 user.go 文件,定义用户模型。模型包含以下字段:

  • Name:用户姓名
  • Username:用户名(唯一)
  • Email:电子邮件(唯一)
  • Password:密码

GORM 会自动为模型添加默认字段,如 IDCreatedAtUpdatedAtDeletedAt

数据库连接

在项目根目录下创建一个 database 文件夹,并添加 client.go 文件,用于管理 MySQL 数据库连接。以下是关键代码:

  • 数据库实例:定义全局变量,用于与数据库通信。
  • 连接函数:接收 MySQL 连接字符串,尝试连接数据库。
  • 迁移函数:确保数据库中存在 users 表,如不存在则自动创建。

运行以下命令安装 GORM 和 MySQL 驱动:

go get -u gorm.io/gorm
go get -u gorm.io/driver/mysql

用户控制器:注册新用户

创建一个 controllers 文件夹,并添加 usercontroller.go 文件,用于处理用户注册逻辑。

在实现注册功能之前,先在 models/user.go 文件中添加辅助函数,用于对密码进行哈希和验证。运行以下命令安装 bcrypt 包:

go get -u golang.org/x/crypto/bcrypt

注册逻辑包括:

  1. 将请求体解析为用户模型。
  2. 对密码进行哈希处理。
  3. 使用 GORM 将用户数据存储到数据库。
  4. 返回用户信息和状态码。

令牌控制器:生成 JWT

创建 tokencontroller.go 文件,定义生成 JWT 的逻辑。以下是关键步骤:

  1. 定义 JWT 密钥和声明结构。
  2. 实现 GenerateJWT 函数,生成带有过期时间的 JWT。
  3. 实现 ValidateToken 函数,验证 JWT 的有效性。

安全控制器:保护端点

创建 securecontroller.go 文件,定义受保护的端点。此端点仅返回一条简单的消息,但需要有效的 JWT 才能访问。

为了避免在每个端点重复验证逻辑,我们将验证逻辑封装到中间件中。


身份验证中间件

在项目根目录下创建一个 middleware 文件夹,并添加 auth.go 文件。中间件的作用是:

  1. 从请求头中提取 JWT。
  2. 使用 ValidateToken 函数验证 JWT。
  3. 如果验证通过,允许请求继续;否则返回 401 错误。

路由设置

main.go 文件中定义路由规则。以下是路由结构:

  • /api/users/register:用户注册
  • /api/token:生成 JWT
  • /api/secured/*:受保护的端点

使用 Gin 的分组功能,可以轻松管理路由和中间件。例如:

secured := router.Group("/api/secured").Use(middleware.Auth())
secured.GET("/ping", controllers.SecurePing)

测试 API

使用 VS Code REST 客户端

在项目根目录下创建一个 rest 文件夹,存放测试请求文件(如 user.resttoken.rest)。确保安装了 VS Code 的 REST 客户端扩展。

测试步骤

  1. 注册用户:向 /api/users/register 发送 POST 请求,注册新用户。
  2. 生成 JWT:向 /api/token 发送 POST 请求,生成 JWT。
  3. 访问受保护端点:使用生成的 JWT 访问 /api/secured/ping

总结

本文详细介绍了如何在 Golang REST API 中实现 JWT 身份验证,包括:

  • JWT 的基础知识
  • 使用 Gin 框架构建 API
  • 使用 GORM 和 MySQL 进行数据持久化
  • 实现用户注册和密码加密
  • 生成和验证 JWT
  • 使用中间件保护端点

通过这些步骤,您可以构建一个功能完善且安全的 REST API。如果您觉得本文对您有帮助,请分享给您的同事和开发者朋友!

原文链接: https://codewithmukesh.com/blog/jwt-authentication-in-golang/