在 Web 开发中,身份验证是一个绕不开的话题。传统的 Session 机制依赖服务器存储用户状态,而在微服务、分布式架构下,这种方式可能会导致状态同步困难。
JWT(JSON Web Token)是一种无状态的、跨平台的身份验证解决方案,非常适合现代 Web API 场景。

本文将带你用 Go 实现一个 JWT 登录验证示例,掌握它的基本原理与使用方式。


一、什么是 JWT

JWT 的结构由三部分组成:

header.payload.signature
  • • Header:声明类型(JWT)和加密算法(如 HMAC SHA256)。
  • • Payload:存放业务数据(如用户ID、角色、过期时间)。
  • • Signature:对前两部分进行签名,保证数据不可篡改。

例如:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.eyJ1c2VyX2lkIjoxLCJleHAiOjE3MDAwMDAwMDB9
.abc123456789xyz

二、实现思路

  1. 1. 用户登录 → 校验账号密码正确 → 生成 JWT 返回给前端。
  2. 2. 前端请求 API → 在 Authorization 头中携带 JWT。
  3. 3. 后端中间件 → 解析 JWT,验证有效性与过期时间。
  4. 4. 通过验证 → 执行后续业务逻辑。

三、代码实现

我们使用 github.com/golang-jwt/jwt/v5 作为 JWT 库。

1. 初始化依赖

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

2. 定义 JWT 工具

package mainimport ("fmt""time""github.com/golang-jwt/jwt/v5"
)var jwtSecret = []byte("my_secret_key")// 生成Token
func GenerateToken(username string) (string, error) {claims := jwt.MapClaims{"username": username,"exp":      time.Now().Add(2 * time.Hour).Unix(),"iat":      time.Now().Unix(),}token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)return token.SignedString(jwtSecret)
}// 验证Token
func ParseToken(tokenString string) (jwt.MapClaims, error) {token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {return jwtSecret, nil})if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {return claims, nil}return nil, err
}

3. 构建简单登录和受保护接口

package mainimport ("encoding/json""fmt""net/http""strings"
)// 模拟用户数据
var users = map[string]string{"alice": "123456","bob":   "654321",
}func loginHandler(w http.ResponseWriter, r *http.Request) {username := r.FormValue("username")password := r.FormValue("password")if pwd, ok := users[username]; !ok || pwd != password {http.Error(w, "用户名或密码错误", http.StatusUnauthorized)return}token, _ := GenerateToken(username)w.Header().Set("Content-Type", "application/json")json.NewEncoder(w).Encode(map[string]string{"token": token})
}func authMiddleware(next http.HandlerFunc) http.HandlerFunc {return func(w http.ResponseWriter, r *http.Request) {authHeader := r.Header.Get("Authorization")if authHeader == "" {http.Error(w, "缺少Authorization头", http.StatusUnauthorized)return}parts := strings.SplitN(authHeader, " ", 2)if len(parts) != 2 || parts[0] != "Bearer" {http.Error(w, "Authorization格式错误", http.StatusUnauthorized)return}claims, err := ParseToken(parts[1])if err != nil {http.Error(w, "无效Token", http.StatusUnauthorized)return}fmt.Printf("JWT解析结果: %+v\n", claims)next.ServeHTTP(w, r)}
}func protectedHandler(w http.ResponseWriter, r *http.Request) {fmt.Fprintln(w, "欢迎访问受保护的资源!")
}func main() {http.HandleFunc("/login", loginHandler)http.HandleFunc("/protected", authMiddleware(protectedHandler))fmt.Println("服务器启动:http://localhost:8080")http.ListenAndServe(":8080", nil)
}

4. 测试流程

  1. 1. 登录获取 Token
curl -X POST "http://localhost:8080/login" -d "username=alice&password=123456"

返回:

{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI..."}
  1. 2. 访问受保护接口
curl -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI..." http://localhost:8080/protected

输出:

欢迎访问受保护的资源!

四、注意事项

  1. 1. Token 过期处理:前端需在过期后重新获取 Token。
  2. 2. Secret 安全性:切勿将 jwtSecret 写死在代码里,可用环境变量管理。
  3. 3. HTTPS:避免 Token 在明文传输中被窃取。
  4. 4. 黑名单机制:如果需要即时让某个 Token 失效,可以维护一个黑名单。

五、总结

JWT 在 Go 中实现并不复杂,但它带来的无状态身份验证机制,非常适合 RESTful API 和分布式架构场景。
通过本示例,你可以快速搭建一个基于 JWT 的登录验证系统,并根据业务需求进行扩展,比如刷新 Token角色权限控制等。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/92836.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/92836.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/92836.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

@RequestMapping接收文件格式的形参(方法参数)

需求:将文件上传到OSS,忽略域名与路径,将文件名以 “img1.png,img2.png,img3.png”保存到数据库中 1、先看结果 后端要接收postman传递的file文件2、SpringBoot接收参数方式 很显然,上面postman上传的地方可以传入多个文件&#x…

【数据分享】2020-2022年我国乡镇的逐日最高气温数据(Shp/Excel格式)

之前我们分享过2020—2022年中国0.01分辨率逐日最高气温栅格数据(可以查看之前的文章获悉详情)!该数据是研究者张凌, 胡英屹等发布在国家冰川冻土沙漠科学数据中心平台上的高分辨最高气温数据。很多小伙伴拿到数据后反馈栅格数据不太方便使用…

为什么C++主函数 main 要写成 int 返回值 | main(int argc, char* argv[]) 这种写法是什么意思?

主函数 main 要写成 int 返回值?main(int argc, char* argv[]) 为什么里面没有 cin 也能读到数据,数据是怎么传进去的?本文将一步步回答这些问题。1. 为什么 main 要写成 intC 标准(ISO/IEC 14882)规定,mai…

【oracle闪回查询】记录字段短时间被修改的记录

SELECT versions_starttime, versions_endtime, versions_operation, versions_xid, [字段1], [字段2] – 替换为实际字段名 FROM 表名 VERSIONS BETWEEN TIMESTAMP SYSTIMESTAMP - INTERVAL ‘15’ MINUTE AND SYSTIMESTAMP --15分钟内 WHERE id ‘目标ID’ – 指定记录的唯…

【软考中级网络工程师】知识点之 IP 组播技术:从原理到实战

目录一、IP 组播技术概述1.1 什么是 IP 组播1.2 IP 组播与其他传输方式对比二、IP 组播地址详解2.1 IPv4 组播地址范围及分类2.2 特殊 IPv4 组播地址示例2.3 IPv6 组播地址结构与特点2.4 IP 组播地址与 MAC 地址的映射关系三、IP 组播协议剖析3.1 IGMP 协议深度解析3.2 PIM 协议…

Akamai Bot Manager智能防护体系解析:边缘计算与AI驱动的反爬虫技术

{ “title”: “Akamai Bot Manager智能防护体系解析:边缘计算与AI驱动的反爬虫技术”, “tags”: “Akamai,Bot Manager,边缘计算,反爬虫,CDN安全,机器学习,威胁检测,网络安全”, “description”: “深度剖析Akamai Bot Manager的边缘计算架构、机器学习检测引擎、…

IIS Express中可以同时加载并使用.net4.0和.NET 2.0的 DLL

<add name"HttpHandler" path"UploadHttpHandler.ashx" verb"*" type"ABC.HttpHandler, ABC"/> </handlers> 如果IIS EXPRESS是加载4.0的环境&#xff0c;可以加载.NET 2.0的DLL吗&#xff1f;在 IIS Express 中&#xff…

STM32 ESP8266 WiFi模块驱动

STM32 ESP8266 WiFi模块驱动 1. 简介 ESP8266是一款高度集成的WiFi芯片&#xff0c;可以为其他设备提供WiFi联网功能。本笔记记录了基于STM32 HAL库的ESP8266驱动实现&#xff0c;包括硬件连接、初始化配置、AT指令交互等关键部分。 项目源码仓库&#xff1a;STM32_Sensor_D…

7 种最佳 DBAN 替代方案,彻底擦除硬盘数据

DBAN&#xff08;Darik 的 Boot and Nuke&#xff09;长期以来一直是安全擦除计算机数据的首选解决方案。然而&#xff0c;尽管 DBAN 广受欢迎&#xff0c;但它也存在一些明显的局限性&#xff0c;这些局限性随着时间的推移变得越来越明显。现在&#xff0c;本文将更详细地探讨…

【K8s】K8s控制器——Deamonset、Statefulset、Job与CronJob

1、Deamonset2、Statefulset3、Job与CronJob一次性作业与周期性作业#- 8.6 #cat > daemonset.yml <<EOF apiVersion: apps/v1 kind: DaemonSet metadata:name: test-demonsetlabels:daemonset: test spec:selector:matchLabels:name: testpodtemplate:metadata:labels…

基于柔性管控终端的新能源汽车充电站有序充电系统设计与实现

摘要&#xff1a;随着新能源汽车的迅猛发展&#xff0c;充电基础设施面临着电力负荷激增、电网稳定性下降等挑战。本文针对当前充电设施无序充电导致的电网压力问题&#xff0c;提出了一种基于柔性管控终端的充电站有序充电系统解决方案。通过分析国内外有序充电技术发展现状&a…

10-docker基于dockerfile自动制作镜像

文章目录一.为什么要学习自动构建镜像1.为什么要学习自动化构建镜像2.根据dockerfile自动构建镜像的流程3.常用的dockerfile指令二.使用dockerfile构建nginx服务镜像&#xff08;FR0M&#xff0c;RUN&#xff0c;CMD&#xff09;1.创建dockerfile的存储路径2.编写dockerfile文件…

如何解决大模型API明明一分钟内只发起了一次请求,却触发了 “Your account reached max request” 的错误

问题背景 在使用 OpenAI SDK 进行 API 调用时&#xff0c;你可能会遇到这样的困惑&#xff1a;明明一分钟内只发起了一次请求&#xff0c;却触发了 “Your account reached max request” 的错误。仔细排查之后发现&#xff0c;并不是 SDK 真正向服务端发送了超限的多次请求&a…

使用Spring Boot+Vue3开源的即时通讯 IM 系统

1. 产品概述V-IM 是一款基于 Electron 和 Vue 3 开发的跨平台即时通讯客户端&#xff0c;目前正在进行2025年版本的开发。该应用提供了丰富的即时通讯功能&#xff0c;支持个人聊天、群组聊天、文件传输等功能&#xff0c;适用于企业内部通讯或团队协作场景。2. 核心功能2.1 用…

在Mac上搭建本地AI工作流:Dify与DeepSeek的完美结合

在Mac上搭建本地AI工作流&#xff1a;Dify与DeepSeek的完美结合 一、Dify平台简介 Dify是一个开源的大语言模型(LLM)应用开发平台&#xff0c;旨在简化和加速生成式AI应用的创建和部署。其名字蕴含着"Define&#xff08;定义&#xff09; Modify&#xff08;修改&#x…

centos出现ping: baidu.com: 未知的名称或服务问题

出现的问题如下&#xff1a;自己电脑连接的是实验室的无线网&#xff0c;宿主机可以上网&#xff0c;但是虚拟机无法ping通百度 解决&#xff1a; 将连接的网络换成自己的手机热点&#xff0c;然后就解决了。。。

GitHub第三方登录全解析:OAuth 2.0流程详解(适合初学者)

&#x1f510; GitHub第三方登录全解析&#xff1a;OAuth 2.0流程详解&#xff08;适合初学者&#xff09; &#x1f31f; 什么是OAuth&#xff1f;为什么需要它&#xff1f; 想象一下&#xff1a;你开发了一个学习笔记应用"DocFlow"&#xff0c;用户需要登录才能使用…

MyBatis持久层实现

MyBatis持久层实现 package com.example.usermanagement.mapper;import com.example.usermanagement.entity.User; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import java.util.List;/*** 用户Mapper接口* Mapper: 标识这是M…

BW处理链日志存储分析与清理

处理链日志存储分析使用程序 RSPC_LOGS_ANALYZE 分析处理链日志占用空间*&---------------------------------------------------------------------* *& Report RSPC_LOGS_ANALYZE *&---------------------------------------------------------------------* *&a…

mysql 简单操作手册

以下是一份 MySQL 日常操作速查手册&#xff0c;包含启动/停止服务、连接/退出客户端、数据库管理、用户权限等常用命令&#xff0c;适用于 macOS&#xff08;Homebrew 安装&#xff09;和 Linux 系统&#xff1a;一、服务管理 &#x1f6a6;操作命令&#xff08;Homebrew&…