go-zero(六) JWT鉴权
go-zero JWT鉴权
还记得我们之前登录功能,返回的信息是token吗? 这个token其实就是JSON Web Token简称JWT,它是一种开放标准(RFC 7519),用于在网络应用环境间安全地传递声明信息。
它是一种基于 JSON 的令牌,由三部分组成:头部(Header)、载荷(Payload)和签名(Signature)。签名是将头部和载荷组合后使用密钥生成的哈希值,用于验证令牌的真实性。
一、配置Auth
Auth是 jwt 密钥,过期等信息配置的 golang 结构体名称, 所以我们要在user-api.yaml中配置Auth
Auth:AccessSecret: "sss12345678" # AccessSecret的值要是8位以上的字符串AccessExpire: 10000 #AccessExpire是过期时间,单位是秒
注意:Auth的名字要和jwt: Auth 这个传入的一样。
接在我们在config.go文件里面定义用来解析配置文件的结构体
type Config struct {rest.RestConfMysqlDb struct {DbSource string `json:"dbSource"`}//增加Auth 结构体Auth struct { AccessSecret stringAccessExpire int64}
}
到这边我们初步配置就完成了
二、生成JWT
为了简化操作,我们直接在loginlogic.go 代码中添加生成token的方法:
/*
secretKey string: 用于加密 JWT 的密钥,通常是一个足够复杂的随机字符串,确保 JWT 不易被伪造。
iat int64: 表示 JWT 的签发时间(Issued At),为一个时间戳,通常是当前时间的 UNIX 时间戳(以秒为单位),可以通过 time.Now().Unix() 获得。
seconds int64: 表示 JWT 的有效时长,单位为秒。这是通过 iat 参数计算出 JWT 的过期时间(exp)。
username string: 自定义有效载荷,通常是是使用用户唯一性的数据作为载体,这里我们为了方便演示使用了username。
*/func getJwtToken(secretKey string, iat, seconds int64,username string) (string, error) {// 创建一个 MapClaims 类型的声明claims := make(jwt.MapClaims)// 计算过期时间claims["exp"] = iat + seconds // 设置 JWT 的过期时间(exp),通常需要一个 UNIX 时间戳claims["iat"] = iat // 设置签发时间(iat)claims["username"] = username // 自定义的负载(payload),可以设置为任何信息,例如用户名、用户ID等// 创建新的 JWTtoken := jwt.New(jwt.SigningMethodHS256) // 使用 HMAC SHA256 签名方法创建新的 JWT// 将声明分配给 JWTtoken.Claims = claims// 使用 secretKey 签名JWT,并返回生成的字符串和错误(如果有)return token.SignedString([]byte(secretKey))
}
JWT有三种加密方式分别是 :SigningMethodHS256、SigningMethodHS384、SigningMethodHS512 ,这里我们用的是hs256
然后修改Login中的代码,添加token生成功能。
go-zero中jwt的传递是在HTTP请求添加名为Authorization的header,形式如下 Authorization: Bearer <token> ,注意 Bearer <token> 之间有空格
func (l *LoginLogic) Login(req *types.LoginRequest) (resp *types.LoginResponse, err error) {// todo: add your logic here and delete this line//因为我们目前还没涉及到jwt鉴权,所以先把token当面message使用userModel := l.svcCtx.UserModeluser, _ := userModel.FindOneByUsername(l.ctx, req.Username)//从配置文件中获取secret 、secret secret := l.svcCtx.Config.Auth.AccessSecretexpire := l.svcCtx.Config.Auth.AccessExpire//生成jwt tokentoken, err := getJwtToken(secret, time.Now().Unix(), expire, req.Username)if err != nil {return nil, errors.New(4, "token生成失败")}//查询username判断是否有数据if user != nil {//如果有数据,密码是否和数据库匹配if req.Password == user.Password {return &types.LoginResponse{Token:"Bearer "+ token, //开头添加Bearer }, nil} else {return nil, errors.New(5, "密码错误")}} else {return nil, errors.New(6, "用户未注册")}
}
注意:从后面我们响应信息默认使用
xhttp.JsonBaseResponseCtx()即zeromicro的x库
运行项目,测试结果如下:

JWT验证go-zero自动帮我们做了,所以我们不需要单独的去写一个验证方法。
三、使用jwt
注册和登录的功能已经实现,现在我们来实现用户的查询和更新功能,这两个功能在正常的业务逻辑中都是需要通过登录实现的,也就是说需要使用jwt来验证和传递信息。
现在我们来编辑新的api文件,并演示如何启用jwt, 在api中我们通过可选参数【jwt:Auth 】来控制是否启用 JWT。具体实现如下:
syntax = "v1"/*
省略注册和登录
*///因为我们想要通过jwt来传递数据,所以我们不需求请求信息
type (GetInfoResponse {Username string `json:"username" `Password string `json:"password" `}
)type (//更新数据我们就简单修改下密码UpdataRequest {Password string `json:"password" `}UpdataResponse {Message string `json:"message"`}
)@server (group: userprefix: /v1jwt: Auth //开启jwt
)
service user-api {@handler GetInfoHandler// 不需要请求信息post /getinfo returns (GetInfoResponse)@handler UpdataHandlerpost /updata (UpdataRequest) returns (UpdataResponse)
}
接下来我们使用goctl生成新的代码
goctl api go --api user.api --dir ./
我们来看下go-zero是怎么帮我们实现jwt认证的,我们先看下routes.go 文件。
func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {/*省略注册和登录的代码*/server.AddRoutes([]rest.Route{{Method: http.MethodPost,Path: "/getinfo",Handler: getinfo.GetInfoHandler(serverCtx),},},//开启jwtrest.WithJwt(serverCtx.Config.Auth.AccessSecret),rest.WithPrefix("/v1"),)server.AddRoutes([]rest.Route{{Method: http.MethodPost,Path: "/updata",Handler: updata.UpdataHandler(serverCtx),},},//开启jwtrest.WithJwt(serverCtx.Config.Auth.AccessSecret),rest.WithPrefix("/v1"),)
}
goctl 帮我在/getinfo和/updata两个路由使用rest.WithJwt开启了jwt验证。
四、获取载体信息
1. 实现信息查询
我们首先去实现查询和更新这两个业务逻辑,到logic目录下打开getinfologic.go 修改代码如下:
func (l *GetInfoLogic) GetInfo() (resp *types.GetInfoResponse, err error) {// todo: add your logic here and delete this line//使用l.ctx.Value() 来获取jwt的内容username := l.ctx.Value("username").(string)usermodel := l.svcCtx.UserModeluser, err := usermodel.FindOneByUsername(l.ctx, username)if err != nil && err != model.ErrNotFound {return nil, errors.New(0, "数据库连接失败")}if user == nil {return nil, errors.New(11, "查询失败,没有该用户信息")}return &types.GetInfoResponse{Username: user.Username,Password: user.Password,}, nilreturn
}
在go-zero中使用l.ctx.Value()来获取数据, 这里我们使用的username,其实就是我们获取token的时候传入的自定义payload, 总而言之就是你传什么字段就获取什么字段。因为Value()是any类型,所以需要对它进行断言。
我们先不传递Authorization的值,运行项目测试一下,可以发现直接报错了

我们可以看下运行日志,提示我们认证失败,没有token

现在添加Authorization的值再测试下,可以看到成功执行:

2. 实现信息修改
func (l *UpdataLogic) Updata(req *types.UpdataRequest) (resp *types.UpdataResponse, err error) {// todo: add your logic here and delete this lineusername := l.ctx.Value("username").(string)usermodel := l.svcCtx.UserModeluser, err := usermodel.FindOneByUsername(l.ctx, username)if err != nil && err != model.ErrNotFound {return nil, errors.New(0, "数据库连接失败")}if user == nil {return nil, errors.New(11, "查询失败,没有该用户信息")}newUser := model.Users{Id: user.Id,Username: user.Username,Password: req.Password, //使用请求响应的密码CreatedAt: user.CreatedAt,}err = usermodel.Update(l.ctx, &newUser)if err != nil {return nil, errors.New(12, "数据更新失败")}return &types.UpdataResponse{Message: "数据更新成功",}, nil}
运行项目测试:

五、JWT 认证失败自定义处理返回
刚刚我们测试了一下JWT认证失败的情况,它直接给我们返回来401代码,这显然不是我们想要的,现在我们来看下JWT 认证失败自定义处理返回。
我们需要在main中定义一个callback,并注册到服务中 , rest.WithUnauthorizedCallback 会全局捕捉jwt认证失败的请求
server := rest.MustNewServer(c.RestConf, rest.WithUnauthorizedCallback(func(w http.ResponseWriter, r *http.Request, err error) {
接下来我们来具体实现它:
//定义一个返回信息
func unauthorizedHandler(w http.ResponseWriter, r *http.Request, err error) {xhttp.JsonBaseResponse(w, "认证失败:"+err.Error())
}func main() {/*....*/
// 在main函数中添加一个callbackserver := rest.MustNewServer(c.RestConf, rest.WithUnauthorizedCallback(unauthorizedHandler))// 自定义处理返回}))/*....*/
}
运行项目,再次测试认证失败的情况:

相关文章:
go-zero(六) JWT鉴权
go-zero JWT鉴权 还记得我们之前登录功能,返回的信息是token吗? 这个token其实就是JSON Web Token简称JWT,它是一种开放标准(RFC 7519),用于在网络应用环境间安全地传递声明信息。 它是一种基于 JSON 的令牌…...
做一个FabricJS.cc的中文文档网站——面向markdown编程
📢欢迎点赞 :👍 收藏 ⭐留言 📝 如有错误敬请指正,赐人玫瑰,手留余香!📢本文作者:由webmote 原创📢作者格言:新的征程,用爱发电&#…...
开发 + 安全:网络安全的协作方法
开发团队和安全团队之间由来已久的紧张关系一直是组织内部摩擦的根源。开发人员优先考虑速度和效率,旨在通过快节奏、迭代的开发周期快速交付功能和产品并高效前进。另一方面,安全团队努力平衡风险和创新,但必须专注于使用护栏保护敏感数据和…...
Next.js- App Router 概览
#题引:我认为跟着官方文档学习不会走歪路 一:App Router与Page Router 在 v13 版本中,Next.js 引入了一个基于 React 服务器组件 构建的新的 App Router,而在这之前,Next.js 使用的是Page Router。 目录结构 pages …...
python oa服务器巡检报告脚本的重构和修改(适应数盾OTP)有空再去改
Two-Step Vertification required: Please enter the mobile app OTPverification code: 01.因为巡检的服务器要双因子认证登录,也就是登录堡垒机时还要输入验证码。这对我的巡检查服务器的工作带来了不便。它的机制是每一次登录,算一次会话…...
【工控】线扫相机小结 第四篇
背景 这一片主要是对第三篇继续补充。话说上一篇讲到了两种模式的切换,上一篇还遗留了一个Bug,在这一篇里进行订正! 代码回顾 /// <summary>/// 其实就是打开触发/// </summary>void SetLineSacanWorkMode(){-----首先设置为帧…...
亲测解决Unpack operator in subscript requires Python 3.11 or newer
这个问题是在小虎想提前定义一个list,然后作为index list来调用另一个list里面的变量出现的问题。 环境 Ubuntu 22.04 + python 3.10 故障代码示例 NoneList = [None] * opt.spatial_dims TargetMask = Target[i] == torch.arange(1...
数据结构 ——— 堆排序算法的实现
目录 前言 向下调整算法(默认建大堆) 堆排序算法的实现(默认升序) 前言 在之前几章学习了如何用向上调整算法和向下调整算法对数组进行建大/小堆数据结构 ——— 向上/向下调整算法将数组调整为升/降序_对数组进行降序排序代码…...
On-Chip-Network之Topology
片上网络拓扑决定了网络中节点和通道之间的物理布局和连接。拓扑对整体网络性价比的影响是巨大的。拓扑决定了消息 必须经过的跳数(或路由器)以及跳数之间的互连长度,从而显著影响网络延迟。由于经过路由器和链路会产生功耗,因此 …...
2024年11月21日Github流行趋势
项目名称:twenty 项目维护者:charlesBochet, lucasbordeau, Weiko, FelixMalfait, bosiraphael项目介绍:正在构建一个由社区支持的现代化Salesforce替代品。项目star数:21,798项目fork数:2,347 项目名称:p…...
第三十八章 IOT 通信协议MQTT协议实现的中间件EMQXDocker安装与验证指南
EMQX概述以及Docker安装与验证指南 一、EMQX概述 EMQX(原名EMQ X),是一款完全开源、高度可伸缩、高可用的分布式MQTT消息服务器。它不仅支持MQTT协议,还兼容CoAP/LwM2M等多种物联网协议,是5G时代万物互联的重要消息引擎。这款软件由杭州映云科技有限公司开发,基于Erlan…...
Flume日志采集系统的部署,实现flume负载均衡,flume故障恢复
目录 安装包 flume的部署 负载均衡测试 故障恢复 安装包 在这里给大家准备好了flume的安装包 通过网盘分享的文件:apache-flume-1.9.0-bin.tar.gz 链接: https://pan.baidu.com/s/1DXMA4PxdDtUQeMB4J62xoQ 提取码: euz7 --来自百度网盘超级会员v4的分享 ----…...
CodiMD导出pdf失败或无中文
CodiMD导出pdf失败,弹出文件保存窗口,有个pdf文件能下载,但是保存的时候提示“网站出问题了”,实际到服务器上看会发现docker崩溃了。 解决办法: 使用最新的CodiMD镜像,如nabo.codimd.dev/hackmdio/hackmd:…...
数字图像处理(2):Verilog基础语法
(1)Verilog常见数据类型: reg型、wire型、integer型、parameter型 (2)Verilog 常见进制:二进制(b或B)、十进制(d或D)、八进制(o或O)、…...
Kafka 工作流程解析:从 Broker 工作原理、节点的服役、退役、副本的生成到数据存储与读写优化
Kafka:分布式消息系统的核心原理与安装部署-CSDN博客 自定义 Kafka 脚本 kf-use.sh 的解析与功能与应用示例-CSDN博客 Kafka 生产者全面解析:从基础原理到高级实践-CSDN博客 Kafka 生产者优化与数据处理经验-CSDN博客 Kafka 工作流程解析:…...
爬虫重定向问题解决
一,问题 做爬虫时会遇到强制重定向的链接,此时可以手动获取重定向后的链接 如下图情况 第二个链接是目标要抓取的,但它是第一个链接重定向过去的,第一个链接接口状态也是302 二,解决方法 请求第一个链接࿰…...
Java技术复习提升 10异常
10 异常 10.1异常介绍及分类 异常捕获 选中后alttabt->选中try-catch 异常就是程序执行中不正常的情况 注意语法和逻辑错误并不是异常 异常分类有两种 error和exception error是错误 虚拟机无法解决的严重问题 exception是其他因为编程错误或者外在因素导致的一般性的问…...
真题-桂城2022年五年级
目录 GC.2022.五年级.01.拍7 输入数据 1 输出数据 1 GC.2022.五年级.02.硬币 输入数据 1 输出数据 1 答案: GC.2022.五年级.03.次大公约数 输入数据 1 输出数据 1 GC.2022.五年级.04.显示器 输入数据 1 输出数据 1 GC.2022.五年级.05.数对 输入数据 1 输…...
android 使用MediaPlayer实现音乐播放--权限请求
在Android应用中,获取本地音乐文件的权限是实现音乐扫描功能的关键步骤之一。随着Android版本的不断更新,从Android 6.0(API级别23)开始,应用需要动态请求权限,而到了android 13以上需要的权限又做了进一步…...
Web开发:ORM框架之使用Freesql的DbFrist封装常见功能
一、调用 public class Program {static string connectionstring "连接字符串(数据库名)";static void Main(string[] args){//1.连接数据库var freesql new FreeSqlBuilder().UseConnectionString(DataType.SqlServer, connectionstring…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...
免费PDF转图片工具
免费PDF转图片工具 一款简单易用的PDF转图片工具,可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件,也不需要在线上传文件,保护您的隐私。 工具截图 主要特点 🚀 快速转换:本地转换,无需等待上…...
代码规范和架构【立芯理论一】(2025.06.08)
1、代码规范的目标 代码简洁精炼、美观,可持续性好高效率高复用,可移植性好高内聚,低耦合没有冗余规范性,代码有规可循,可以看出自己当时的思考过程特殊排版,特殊语法,特殊指令,必须…...
云安全与网络安全:核心区别与协同作用解析
在数字化转型的浪潮中,云安全与网络安全作为信息安全的两大支柱,常被混淆但本质不同。本文将从概念、责任分工、技术手段、威胁类型等维度深入解析两者的差异,并探讨它们的协同作用。 一、核心区别 定义与范围 网络安全:聚焦于保…...
如何在Windows本机安装Python并确保与Python.NET兼容
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...
leetcode73-矩阵置零
leetcode 73 思路 记录 0 元素的位置:遍历整个矩阵,找出所有值为 0 的元素,并将它们的坐标记录在数组zeroPosition中置零操作:遍历记录的所有 0 元素位置,将每个位置对应的行和列的所有元素置为 0 具体步骤 初始化…...
Qwen系列之Qwen3解读:最强开源模型的细节拆解
文章目录 1.1分钟快览2.模型架构2.1.Dense模型2.2.MoE模型 3.预训练阶段3.1.数据3.2.训练3.3.评估 4.后训练阶段S1: 长链思维冷启动S2: 推理强化学习S3: 思考模式融合S4: 通用强化学习 5.全家桶中的小模型训练评估评估数据集评估细节评估效果弱智评估和民间Arena 分析展望 如果…...
RushDB开源程序 是现代应用程序和 AI 的即时数据库。建立在 Neo4j 之上
一、软件介绍 文末提供程序和源码下载 RushDB 改变了您处理图形数据的方式 — 不需要 Schema,不需要复杂的查询,只需推送数据即可。 二、Key Features ✨ 主要特点 Instant Setup: Be productive in seconds, not days 即时设置 :在几秒钟…...
