go jwt如何支持refresh-token
在 Go 里用 JWT 支持 refresh token核心思路是用两个 token一个短期有效的access_token用来日常访问接口一个长期有效、专门用来换取新 access_token 的refresh_token。下面是一个标准的设计和实现方案你可以参考。1. 核心设计思路这是“双令牌”机制的基础能让你在不影响用户体验的同时保证安全性。Access Token访问令牌短期有效通常设为 15分钟到2小时。它包含了用户身份信息和权限用于保护 API 接口。Refresh Token刷新令牌长期有效通常设为 24小时到7天。它只用于请求新的 Access Token不应包含业务相关的自定义数据。整体流程像这样登录服务端同时生成 access_token 和 refresh_token将 refresh_token 的哈希值存入数据库绝不存储原始 token然后把两个 token 都返回给客户端。访问客户端每次请求都带上 access_token。服务端验证其有效性通过则放行。刷新当 access_token 过期客户端用 refresh_token 去请求/refresh接口。服务端验证后生成一对全新的 token返回给客户端并废弃旧的 refresh_token。退出直接从数据库中删除或使该用户的 refresh_token 失效。2. 具体实现步骤第一步定义 Token 管理器和结构体首先你需要一个核心结构来管理 token 的生成和验证。可以基于github.com/golang-jwt/jwt/v5这个主流库来封装。goimport ( time github.com/golang-jwt/jwt/v5 ) // JWTManager 负责管理 JWT type JWTManager struct { secretKey []byte accessTokenExpiry time.Duration refreshTokenExpiry time.Duration issuer string } // NewJWTManager 是构造函数 func NewJWTManager(secret string, accessExp, refreshExp time.Duration, issuer string) *JWTManager { return JWTManager{ secretKey: []byte(secret), accessTokenExpiry: accessExp, refreshTokenExpiry: refreshExp, issuer: issuer, } }第二步生成一对 Token登录成功后就调用这个方法同时生成 access_token 和 refresh_token。go// TokenPair 包含返回给客户端的两个 token 和它们的过期时间 type TokenPair struct { AccessToken string json:access_token RefreshToken string json:refresh_token AccessTokenExpiresAt time.Time json:access_token_expires_at RefreshTokenExpiresAt time.Time json:refresh_token_expires_at } // GenerateTokenPair 为给定用户生成一对新 token func (m *JWTManager) GenerateTokenPair(userID string) (*TokenPair, error) { now : time.Now() accessExp : now.Add(m.accessTokenExpiry) refreshExp : now.Add(m.refreshTokenExpiry) // 1. 生成 Access Token (携带用户自定义信息) accessClaims : jwt.RegisteredClaims{ Subject: userID, Issuer: m.issuer, IssuedAt: jwt.NewNumericDate(now), ExpiresAt: jwt.NewNumericDate(accessExp), } accessToken, err : jwt.NewWithClaims(jwt.SigningMethodHS256, accessClaims).SignedString(m.secretKey) if err ! nil { return nil, err } // 2. 生成 Refresh Token (只含标准声明不含业务数据) refreshClaims : jwt.RegisteredClaims{ Subject: userID, Issuer: m.issuer, IssuedAt: jwt.NewNumericDate(now), ExpiresAt: jwt.NewNumericDate(refreshExp), } refreshToken, err : jwt.NewWithClaims(jwt.SigningMethodHS256, refreshClaims).SignedString(m.secretKey) if err ! nil { return nil, err } return TokenPair{ AccessToken: accessToken, RefreshToken: refreshToken, AccessTokenExpiresAt: accessExp, RefreshTokenExpiresAt: refreshExp, }, nil }第三步实现刷新逻辑这是最关键的步骤。客户端用 refresh_token 来换取新的 access_token。go// RefreshAccessToken 验证 refresh token 并生成新的 access token func (m *JWTManager) RefreshAccessToken(refreshTokenStr string) (string, error) { // 1. 验证 refresh token 的签名和有效期 token, err : jwt.Parse(refreshTokenStr, func(token *jwt.Token) (interface{}, error) { return m.secretKey, nil }) if err ! nil { return , err // token 无效或过期 } if !token.Valid { return , jwt.ErrTokenInvalid } // 2. 从 token 中提取用户 ID (subject) claims, ok : token.Claims.(jwt.MapClaims) if !ok { return , jwt.ErrTokenInvalid } userID, ok : claims[sub].(string) if !ok || userID { return , jwt.ErrTokenInvalid } // 3. 生成一个全新的 access token newClaims : jwt.RegisteredClaims{ Subject: userID, Issuer: m.issuer, IssuedAt: jwt.NewNumericDate(time.Now()), ExpiresAt: jwt.NewNumericDate(time.Now().Add(m.accessTokenExpiry)), } newAccessToken, err : jwt.NewWithClaims(jwt.SigningMethodHS256, newClaims).SignedString(m.secretKey) if err ! nil { return , err } return newAccessToken, nil }3. 数据库层安全地存储 Refresh Token为了安全和控制强烈建议服务端跟踪每个 refresh_token而不是完全无状态。可以在数据库创建一张sessions或refresh_tokens表字段说明id主键user_id关联的用户 IDrefresh_token_hash存储 refresh_token 的哈希值 (例如 SHA256)用于安全比对expires_attoken 的过期时间revoked_at退出或轮换时标记为已撤销在登录时先计算 refresh_token 的哈希存入refresh_token_hash在刷新时根据客户端传来的 refresh_token 计算出哈希去数据库匹配。这里的关键动作是“令牌轮换Token Rotation”每次刷新时不仅要生成新的 access_token还要生成一个新的 refresh_token并用新的哈希替换掉数据库中旧的记录。这样可以防止一个 refresh_token 被多次使用。go// 在刷新接口的处理函数中伪代码逻辑 func handleRefresh(refreshTokenStr string) { // 1. 计算哈希值并从 DB 查找 hash : sha256.Sum256([]byte(refreshTokenStr)) session, err : db.FindByRefreshHash(hex.EncodeToString(hash[:])) if err ! nil { // token 无效或已撤销 return } // 2. 验证 token 是否过期 (JWT 库会做但数据库也要校验) if session.ExpiresAt.Before(time.Now()) { return } // 3. 生成全新的 token 对 (这就是 token rotation) newPair, err : jwtManager.GenerateTokenPair(session.UserID) // 4. 原子性地在数据库中删除旧记录插入新记录 err db.ReplaceRefreshHash(session.RefreshTokenHash, newPair.RefreshTokenHash) if err ! nil { // 处理错误... } // 5. 将新的 access_token 和 refresh_token 返回给客户端 return newPair }总结一下核心库用github.com/golang-jwt/jwt/v5来创建和验证 JWT。双令牌access_token短期、携带业务信息refresh_token长期、只用于刷新。安全存储服务端存 refresh_token 的哈希值而不是原文。令牌轮换每次刷新都颁发全新的access_tokenrefresh_token对并废弃旧的 refresh_token这是推荐的最佳实践。如果想看一个更完整的项目示例可以参考github.com/Jaro-c/authcore这个库的 auth/jwt 模块它很好地演示了从登录到轮换的完整流程

相关新闻

最后50天!PMP旧考纲末班车:别再盲目刷题了,用这4个“错题复盘法”直接冲

最后50天!PMP旧考纲末班车:别再盲目刷题了,用这4个“错题复盘法”直接冲

不要用战术上的勤奋掩盖战略上的懒惰兄弟们好。今天是7月17日。2026年9月PMP中文报名昨天已经正式开启。7月23日16:00全国统一截止——窗口只剩不到一周。2026年9月12日,是中国大陆PMP旧考纲的最后一场考试。12月9日起将全面启用PMBOK第八版和新考纲。9月12日这趟末…

2026/7/18 20:02:00阅读更多 →
uniapp vue3 微信小程序使用echarts显示图表

uniapp vue3 微信小程序使用echarts显示图表

真是恶心到家了&#xff0c;研究了一天半的时间&#xff0c;终于搞出来了&#xff0c;现在和大家分享一下代码。<template><view class"chart-container"><canvas id"myChart" type"2d" canvas-id"myChart" style"…

2026/7/18 20:00:00阅读更多 →
git与github的使用手册

git与github的使用手册

一、前期准备安装&#xff08;略&#xff09;配置配置 name 和 email git config --global user.name "xxxx" git config --global user.email "xxxxxx.xxx"使用 git&#xff1a;查看当前仓库的状态 git status初始化仓库 git init文件状态&#xff1a; 未…

2026/7/18 20:00:00阅读更多 →
如何通过QQ空间导出助手构建个人数字记忆档案馆

如何通过QQ空间导出助手构建个人数字记忆档案馆

如何通过QQ空间导出助手构建个人数字记忆档案馆 【免费下载链接】QZoneExport QQ空间导出助手&#xff0c;用于备份QQ空间的说说、日志、私密日记、相册、视频、留言板、QQ好友、收藏夹、分享、最近访客为文件&#xff0c;便于迁移与保存 项目地址: https://gitcode.com/gh_m…

2026/7/18 21:10:35阅读更多 →
RUFI洗衣液适合床品吗

RUFI洗衣液适合床品吗

RUFI洗衣液适合床品&#xff0c;但床品不是单纯追求“越香越好”的场景。枕套、被套、床单贴近脸和身体&#xff0c;最重要的是洗后清爽、晾干彻底、入睡时气味不压人。RUFI酵素香氛洗衣精华原液的价值&#xff0c;在这里主要体现在净味、柔软和轻香。床品需要干净底色床品一周…

2026/7/18 21:10:35阅读更多 →
Agent 是什么?用你听得懂的方式讲清楚

Agent 是什么?用你听得懂的方式讲清楚

不是又一个新的科技概念&#xff0c;而是 AI 终于开始「自己动手」了&#xfffd;&#xfffd; 约 3500 字 ⏱ 阅读约 7 分钟这两年你肯定没少看到「Agent」这个词。打开科技新闻&#xff0c;AI 圈的人在聊 Agent&#xff1b;打开社交媒体&#xff0c;产品博主在推荐 Agent …

2026/7/18 21:10:35阅读更多 →
救命!2026年AI论文写作工具排行榜,写论文卡壳的学生党直接抄作业

救命!2026年AI论文写作工具排行榜,写论文卡壳的学生党直接抄作业

作为熬了 3 年论文、前后踩过十几款 AI 写作工具坑的老学长&#xff0c;今天直接给大家上硬货 ——2026 年 AI 写论文工具排行榜&#xff01;结合《2025 论文写作工具白皮书》的用户实测数据&#xff0c;还有我从本科毕设到硕士小论文的全程使用体验&#xff0c;精选出 7 款真正…

2026/7/18 21:10:35阅读更多 →
解决昇腾910B多容器部署Qwen3.6-27b引发的HCCL通信端口冲突问题

解决昇腾910B多容器部署Qwen3.6-27b引发的HCCL通信端口冲突问题

环境&#xff1a;华为昇腾910B 8 | vLLM-Ascend v0.20.2rc1 | Docker 问题&#xff1a;同一台机器启动多个Docker容器运行TP并行推理时&#xff0c;HCCL通信端口冲突导致初始化失败一、问题背景在单台8卡昇腾910B服务器上&#xff0c;需要同时部署以下模型服务&#xff1a;模型…

2026/7/18 21:10:35阅读更多 →
实体服装店急补货,如何判断哪个线上平台到货更快?

实体服装店急补货,如何判断哪个线上平台到货更快?

急补货是实体服装店最考验供应链的时刻。换季前一周发现爆款备少了&#xff0c;周末活动前临时要补几个款&#xff0c;或者老顾客点名要某款明天就来拿——这些场景下&#xff0c;到货速度直接决定你能不能接住这波生意&#xff0c;慢一天可能就错过整个销售窗口。问题是&#…

2026/7/18 21:08:34阅读更多 →
VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异

VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异

VSCode TypeScript 环境配置对比&#xff1a;全局安装 vs 项目本地安装的4个关键差异当你在VSCode中启动一个新的TypeScript项目时&#xff0c;第一个技术决策往往从安装方式开始。这个看似简单的选择——全局安装还是项目本地安装——实际上会深刻影响你的开发流程、团队协作和…

2026/7/18 10:49:13阅读更多 →
智慧树刷课插件:5分钟实现自动化学习的智能助手

智慧树刷课插件:5分钟实现自动化学习的智能助手

智慧树刷课插件&#xff1a;5分钟实现自动化学习的智能助手 【免费下载链接】zhihuishu 智慧树刷课插件&#xff0c;自动播放下一集、1.5倍速度、无声 项目地址: https://gitcode.com/gh_mirrors/zh/zhihuishu 智慧树刷课插件是一款专为智慧树在线教育平台设计的Chrome浏…

2026/7/18 8:49:08阅读更多 →
Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案

Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案

Steam创意工坊下载器WorkshopDL&#xff1a;跨平台游戏模组获取的终极解决方案 【免费下载链接】WorkshopDL WorkshopDL - The Best Steam Workshop Downloader 项目地址: https://gitcode.com/gh_mirrors/wo/WorkshopDL 你是否在GOG或Epic Games Store购买了心仪的游戏…

2026/7/18 14:49:24阅读更多 →
从模糊意图到可执行指令:Claude PRD中Prompt Engineering与需求颗粒度的5级映射法则

从模糊意图到可执行指令:Claude PRD中Prompt Engineering与需求颗粒度的5级映射法则

更多请点击&#xff1a; https://kaifayun.com 第一章&#xff1a;从模糊意图到可执行指令&#xff1a;Claude PRD中Prompt Engineering与需求颗粒度的5级映射法则 在Claude驱动的产品需求文档&#xff08;PRD&#xff09;生成实践中&#xff0c;原始业务意图往往以自然语言片…

2026/7/18 0:00:14阅读更多 →
Cursor配置生成失效?3大隐藏陷阱+4行修复代码,资深工程师连夜整理的紧急补救清单

Cursor配置生成失效?3大隐藏陷阱+4行修复代码,资深工程师连夜整理的紧急补救清单

更多请点击&#xff1a; https://codechina.net 第一章&#xff1a;Cursor配置生成失效&#xff1f;3大隐藏陷阱4行修复代码&#xff0c;资深工程师连夜整理的紧急补救清单 Cursor 配置生成突然失效&#xff0c;是近期高频报障场景。表面看是 cursor.config.json 未更新或 LSP…

2026/7/18 0:00:14阅读更多 →
某智驾大牛创业

某智驾大牛创业

作者&#xff1a;钟声编辑&#xff1a;Mark出品&#xff1a;红色星际头图&#xff1a;智能驾驶图片据悉&#xff0c;国内某头部智驾公司端到端模型技术大牛Z投身创业&#xff0c;并且已经拿到融资。Z不仅是该头部公司内部最年轻的对标阿里P10级别技术负责⼈&#xff0c;更是业内…

2026/7/18 0:00:14阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时&#xff0c;发现推理速度只有可怜的 1-2 FPS&#xff0c;而别人的演示视频却能跑到 30 FPS 以上&#xff0c;那么问题很可能不在模型本身&#xff0c;而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后&#xff0c;会直接使用官方示例…

2026/7/17 22:48:46阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一&#xff1a;为什么你需要了解 Coze 和 Dify&#xff1f;如果你对 AI 应用开发感兴趣&#xff0c;但一看到“大模型”、“智能体”、“工作流”这些词就头疼&#xff0c;觉得门槛太高&#xff0c;那这篇文章就是为你准备的。很多开发者&#xff0c;包括我自己&#…

2026/7/18 14:49:24阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会&#xff1a;配图一直是个让人头疼的问题。2026年&#xff0c;AI生图工具已经非常成熟了&#xff0c;但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1&#xff1a;速度之王2026年6月11日&#xff0c…

2026/7/18 18:49:35阅读更多 →