当前位置: 首页 > news >正文

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有三种加密方式分别是 :SigningMethodHS256SigningMethodHS384SigningMethodHS512 ,这里我们用的是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鉴权 还记得我们之前登录功能&#xff0c;返回的信息是token吗&#xff1f; 这个token其实就是JSON Web Token简称JWT,它是一种开放标准&#xff08;RFC 7519&#xff09;&#xff0c;用于在网络应用环境间安全地传递声明信息。 它是一种基于 JSON 的令牌&#xf…...

做一个FabricJS.cc的中文文档网站——面向markdown编程

&#x1f4e2;欢迎点赞 &#xff1a;&#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff0c;赐人玫瑰&#xff0c;手留余香&#xff01;&#x1f4e2;本文作者&#xff1a;由webmote 原创&#x1f4e2;作者格言&#xff1a;新的征程&#xff0c;用爱发电&#…...

开发 + 安全:网络安全的协作方法

开发团队和安全团队之间由来已久的紧张关系一直是组织内部摩擦的根源。开发人员优先考虑速度和效率&#xff0c;旨在通过快节奏、迭代的开发周期快速交付功能和产品并高效前进。另一方面&#xff0c;安全团队努力平衡风险和创新&#xff0c;但必须专注于使用护栏保护敏感数据和…...

Next.js- App Router 概览

#题引&#xff1a;我认为跟着官方文档学习不会走歪路 一&#xff1a;App Router与Page Router 在 v13 版本中&#xff0c;Next.js 引入了一个基于 React 服务器组件 构建的新的 App Router&#xff0c;而在这之前&#xff0c;Next.js 使用的是Page Router。 目录结构 pages …...

python oa服务器巡检报告脚本的重构和修改(适应数盾OTP)有空再去改

Two-Step Vertification required&#xff1a; Please enter the mobile app OTPverification code: 01.因为巡检的服务器要双因子认证登录&#xff0c;也就是登录堡垒机时还要输入验证码。这对我的巡检查服务器的工作带来了不便。它的机制是每一次登录&#xff0c;算一次会话…...

【工控】线扫相机小结 第四篇

背景 这一片主要是对第三篇继续补充。话说上一篇讲到了两种模式的切换&#xff0c;上一篇还遗留了一个Bug&#xff0c;在这一篇里进行订正&#xff01; 代码回顾 /// <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...

数据结构 ——— 堆排序算法的实现

目录 前言 向下调整算法&#xff08;默认建大堆&#xff09; 堆排序算法的实现&#xff08;默认升序&#xff09; 前言 在之前几章学习了如何用向上调整算法和向下调整算法对数组进行建大/小堆数据结构 ——— 向上/向下调整算法将数组调整为升/降序_对数组进行降序排序代码…...

On-Chip-Network之Topology

片上网络拓扑决定了网络中节点和通道之间的物理布局和连接。拓扑对整体网络性价比的影响是巨大的。拓扑决定了消息 必须经过的跳数&#xff08;或路由器&#xff09;以及跳数之间的互连长度&#xff0c;从而显著影响网络延迟。由于经过路由器和链路会产生功耗&#xff0c;因此 …...

2024年11月21日Github流行趋势

项目名称&#xff1a;twenty 项目维护者&#xff1a;charlesBochet, lucasbordeau, Weiko, FelixMalfait, bosiraphael项目介绍&#xff1a;正在构建一个由社区支持的现代化Salesforce替代品。项目star数&#xff1a;21,798项目fork数&#xff1a;2,347 项目名称&#xff1a;p…...

第三十八章 IOT 通信协议MQTT协议实现的中间件EMQXDocker安装与验证指南

EMQX概述以及Docker安装与验证指南 一、EMQX概述 EMQX(原名EMQ X),是一款完全开源、高度可伸缩、高可用的分布式MQTT消息服务器。它不仅支持MQTT协议,还兼容CoAP/LwM2M等多种物联网协议,是5G时代万物互联的重要消息引擎。这款软件由杭州映云科技有限公司开发,基于Erlan…...

Flume日志采集系统的部署,实现flume负载均衡,flume故障恢复

目录 安装包 flume的部署 负载均衡测试 故障恢复 安装包 在这里给大家准备好了flume的安装包 通过网盘分享的文件&#xff1a;apache-flume-1.9.0-bin.tar.gz 链接: https://pan.baidu.com/s/1DXMA4PxdDtUQeMB4J62xoQ 提取码: euz7 --来自百度网盘超级会员v4的分享 ----…...

CodiMD导出pdf失败或无中文

CodiMD导出pdf失败&#xff0c;弹出文件保存窗口&#xff0c;有个pdf文件能下载&#xff0c;但是保存的时候提示“网站出问题了”&#xff0c;实际到服务器上看会发现docker崩溃了。 解决办法&#xff1a; 使用最新的CodiMD镜像&#xff0c;如nabo.codimd.dev/hackmdio/hackmd:…...

数字图像处理(2):Verilog基础语法

&#xff08;1&#xff09;Verilog常见数据类型&#xff1a; reg型、wire型、integer型、parameter型 &#xff08;2&#xff09;Verilog 常见进制&#xff1a;二进制&#xff08;b或B&#xff09;、十进制&#xff08;d或D&#xff09;、八进制&#xff08;o或O&#xff09;、…...

Kafka 工作流程解析:从 Broker 工作原理、节点的服役、退役、副本的生成到数据存储与读写优化

Kafka&#xff1a;分布式消息系统的核心原理与安装部署-CSDN博客 自定义 Kafka 脚本 kf-use.sh 的解析与功能与应用示例-CSDN博客 Kafka 生产者全面解析&#xff1a;从基础原理到高级实践-CSDN博客 Kafka 生产者优化与数据处理经验-CSDN博客 Kafka 工作流程解析&#xff1a…...

爬虫重定向问题解决

一&#xff0c;问题 做爬虫时会遇到强制重定向的链接&#xff0c;此时可以手动获取重定向后的链接 如下图情况 第二个链接是目标要抓取的&#xff0c;但它是第一个链接重定向过去的&#xff0c;第一个链接接口状态也是302 二&#xff0c;解决方法 请求第一个链接&#xff0…...

Java技术复习提升 10异常

10 异常 10.1异常介绍及分类 异常捕获 选中后alttabt->选中try-catch 异常就是程序执行中不正常的情况 注意语法和逻辑错误并不是异常 异常分类有两种 error和exception error是错误 虚拟机无法解决的严重问题 exception是其他因为编程错误或者外在因素导致的一般性的问…...

真题-桂城2022年五年级

目录 GC.2022.五年级.01.拍7 输入数据 1 输出数据 1 GC.2022.五年级.02.硬币 输入数据 1 输出数据 1 答案&#xff1a; GC.2022.五年级.03.次大公约数 输入数据 1 输出数据 1 GC.2022.五年级.04.显示器 输入数据 1 输出数据 1 GC.2022.五年级.05.数对 输入数据 1 输…...

android 使用MediaPlayer实现音乐播放--权限请求

在Android应用中&#xff0c;获取本地音乐文件的权限是实现音乐扫描功能的关键步骤之一。随着Android版本的不断更新&#xff0c;从Android 6.0&#xff08;API级别23&#xff09;开始&#xff0c;应用需要动态请求权限&#xff0c;而到了android 13以上需要的权限又做了进一步…...

Web开发:ORM框架之使用Freesql的DbFrist封装常见功能

一、调用 public class Program {static string connectionstring "连接字符串&#xff08;数据库名&#xff09;";static void Main(string[] args){//1.连接数据库var freesql new FreeSqlBuilder().UseConnectionString(DataType.SqlServer, connectionstring…...

【杂谈】-递归进化:人工智能的自我改进与监管挑战

递归进化&#xff1a;人工智能的自我改进与监管挑战 文章目录 递归进化&#xff1a;人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管&#xff1f;3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

进程地址空间(比特课总结)

一、进程地址空间 1. 环境变量 1 &#xff09;⽤户级环境变量与系统级环境变量 全局属性&#xff1a;环境变量具有全局属性&#xff0c;会被⼦进程继承。例如当bash启动⼦进程时&#xff0c;环 境变量会⾃动传递给⼦进程。 本地变量限制&#xff1a;本地变量只在当前进程(ba…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命

在华东塑料包装行业面临限塑令深度调整的背景下&#xff0c;江苏艾立泰以一场跨国资源接力的创新实践&#xff0c;重新定义了绿色供应链的边界。 跨国回收网络&#xff1a;废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点&#xff0c;将海外废弃包装箱通过标准…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

【Go】3、Go语言进阶与依赖管理

前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课&#xff0c;做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程&#xff0c;它的核心机制是 Goroutine 协程、Channel 通道&#xff0c;并基于CSP&#xff08;Communicating Sequential Processes&#xff0…...

Linux云原生安全:零信任架构与机密计算

Linux云原生安全&#xff1a;零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言&#xff1a;云原生安全的范式革命 随着云原生技术的普及&#xff0c;安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测&#xff0c;到2025年&#xff0c;零信任架构将成为超…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结&#xff1a; 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析&#xff1a; 实际业务去理解体会统一注…...

Ascend NPU上适配Step-Audio模型

1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统&#xff0c;支持多语言对话&#xff08;如 中文&#xff0c;英文&#xff0c;日语&#xff09;&#xff0c;语音情感&#xff08;如 开心&#xff0c;悲伤&#xff09;&#x…...

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包&#xff08;Closure&#xff09;&#xff1f;闭包有什么应用场景和潜在问题&#xff1f;2.解释 JavaScript 的作用域链&#xff08;Scope Chain&#xff09; 二、原型与继承3.原型链是什么&#xff1f;如何实现继承&a…...

Web 架构之 CDN 加速原理与落地实践

文章目录 一、思维导图二、正文内容&#xff08;一&#xff09;CDN 基础概念1. 定义2. 组成部分 &#xff08;二&#xff09;CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 &#xff08;三&#xff09;CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 &#xf…...