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

Gin + Ant Design Pro JWT认证

文章目录

  • 一:介绍
  • 二:Gin JWT 后台
    • 1. `Claims `定义
    • 2. 创建和解析Token
    • 3. Gin中间件编写
    • 4. 辅助函数
  • 三:Ant Design Pro JWT认证
  • 四:Gin中间件和使用示范

一:介绍

  • JWT现在比较流行的认证方式,微服务中使用特别常见。
  • JWT标准格式

在HTTP请求添加名为Authorization的header,形式如下: (token前面Bearer 是标准前缀字符串)
Authorization: Bearer

  • Go JWT 结构体Claims,可以理解为需要保存的信息,加密后会存储在token中,解密后会从token自动解析出来

配合ant design pro前端实现需要解决以下问题:

  • JWT TOKEN需要存储哪些字段以及定义,如何创建和解析
  • 前端发送请求时如何自动添加JWT认证信息
  • JWT TOKEN过期后,前后端如何配合自动刷新

二:Gin JWT 后台

使用库github.com/golang-jwt/jwt/v5

1. Claims 定义

jwt.RegisteredClaimsgithub.com/golang-jwt/jwt/v5预设的标准claims,后面用到其ExpiresAt过期时间字段,UserClaims 为自定义存储的字段,最终加密到token中的是jwtClaims结构

type UserClaims struct {
// 可以添加字段存储其他信息UserID   uint   `json:"userId"`RoleID   uint   `json:"roleId"`UserName string `json:"username"`
}type jwtClaims struct {UserClaimsjwt.RegisteredClaims
}

2. 创建和解析Token

expireHoursrefreshHours分别是设置过期时间,以及距离过期时间多久返回新token,后续在gin中间件中判断,方式是在Header中返回x-refresh-tokennewToken

type JWT struct {secret       []byteexpireHours  time.TimerefreshHours time.Duration
}// j := NewJWT("密钥", 2, 1)
// token过期时间是2小时, 距离过期时间还有1小时时在`Header`中返回`x-refresh-token`:`newToken`
func NewJWT(secret string, expireHours int, refreshHours int) *JWT {return &JWT{secret:       []byte(secret),expireHours:  time.Now().Add(time.Duration(expireHours) * time.Hour),refreshHours: time.Hour * time.Duration(refreshHours),}
}func (j *JWT) CreateToken(u UserClaims) (string, error) {token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwtClaims{UserClaims: u,RegisteredClaims: jwt.RegisteredClaims{ExpiresAt: jwt.NewNumericDate(j.expireHours),IssuedAt:  jwt.NewNumericDate(time.Now()),},})return token.SignedString(j.secret)
}func (j *JWT) ParseToken(tokenString string) (*jwtClaims, error) {token, err := jwt.ParseWithClaims(tokenString, &jwtClaims{}, func(token *jwt.Token) (interface{}, error) {return j.secret, nil})if err != nil {return nil, err}if claims, ok := token.Claims.(*jwtClaims); ok && token.Valid {return claims, nil} else {return nil, errors.New("Token无效")}
}

3. Gin中间件编写

type BaseResponse struct {Success      bool   `json:"success"`Data         any    `json:"data"`Message      string `json:"message"`ErrorMessage string `json:"errorMessage"`
}func OkWithData(c *gin.Context, data any) {c.JSON(200, BaseResponse{Success: true, Data: data})
}func OkWithMsg(c *gin.Context, msg string) {c.JSON(200, BaseResponse{Success: true, Message: msg})
}func Fail(c *gin.Context, errMsg string) {c.JSON(200, BaseResponse{Success: false, ErrorMessage: errMsg})
}
// 使用如下:
// // token过期时间是2小时, 距离过期时间还有1小时时在`Header`中返回`x-refresh-token`:`newToken`
// j := NewJWT("密钥", 2, 1)
// r.USE(JWTAuth(j))
func JWTAuth(j *JWT) gin.HandlerFunc {return func(c *gin.Context) {token := c.Request.Header.Get("Authorization")token = strings.TrimPrefix(token, "Bearer ")claims, err := j.ParseToken(token)if err != nil {response.Fail(c, "Token错误: "+err.Error())c.Abort()return}if time.Since(claims.ExpiresAt.Local()) < j.refreshHours {newToken, err := j.CreateToken(claims.UserClaims)if err != nil {response.Fail(c, "Token刷新错误: "+err.Error())c.Abort()return}c.Header("x-refresh-token", newToken)}c.Set("claims", claims)c.Next()}}

4. 辅助函数

gin中直接调用该函数可以方便的获取到存储的机构体信息

func GetUserToken(c *gin.Context) *UserClaims {claims, _ := c.Get("claims")if claims == nil {return &UserClaims{}}return &claims.(*jwtClaims).UserClaims
}

三:Ant Design Pro JWT认证

处理登录请求后返回jwt token使用localStorage.setItem('jwt', token)存储起来
app.tsx的文件request定义中添加拦截器,实现方法:

  • 请求前,在header中添加头·Authorization·: 'Bearer ’ + localStorage.getItem(‘jwt’) || ‘’
  • 请求后,检测header中是否存在x-refresh-token,存在的话更新token,目的是防止token过期自动刷新
    实现如下:
function setToken(token: string) {localStorage.setItem('jwt', token);
}function getToken(): string {return localStorage.getItem('jwt') || '';
}export const request = {...errorConfig,// 请求前拦截器requestInterceptors: [(url: string, options: RequestConfig) => {const authHeader = { Authorization: 'Bearer ' + getToken() };return {url: `${url}`,options: { ...options, interceptors: true, headers: authHeader },};},],// 请求后拦截器responseInterceptors: [(response: Response, options: RequestConfig) => {if (response.headers.has('x-refresh-token')) {setToken(response.headers.get('x-refresh-token') || '');}return response;},],
};

四:Gin中间件和使用示范

jwt_middleware.go

package middlewareimport ("errors""strings""time""github.com/gin-gonic/gin""github.com/golang-jwt/jwt/v5"
)// 可以添加字段存储其他信息
type UserClaims struct {UserID   uint   `json:"userId"`RoleID   uint   `json:"roleId"`UserName string `json:"username"`
}type jwtClaims struct {UserClaimsjwt.RegisteredClaims
}type JWT struct {secret       []byteexpireHours  time.TimerefreshHours time.Duration
}// j := NewJWT("密钥", 2, 1)
// token过期时间是2小时, 距离过期时间还有1小时时在`Header`中返回`x-refresh-token`:`newToken`
func NewJWT(secret string, expireHours int, refreshHours int) *JWT {return &JWT{secret:       []byte(secret),expireHours:  time.Now().Add(time.Duration(expireHours) * time.Hour),refreshHours: time.Hour * time.Duration(refreshHours),}
}func (j *JWT) CreateToken(u UserClaims) (string, error) {token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwtClaims{UserClaims: u,RegisteredClaims: jwt.RegisteredClaims{ExpiresAt: jwt.NewNumericDate(j.expireHours),IssuedAt:  jwt.NewNumericDate(time.Now()),},})return token.SignedString(j.secret)
}func (j *JWT) ParseToken(tokenString string) (*jwtClaims, error) {token, err := jwt.ParseWithClaims(tokenString, &jwtClaims{}, func(token *jwt.Token) (interface{}, error) {return j.secret, nil})if err != nil {return nil, err}if claims, ok := token.Claims.(*jwtClaims); ok && token.Valid {return claims, nil} else {return nil, errors.New("Token无效")}
}// 使用如下:
// // token过期时间是2小时, 距离过期时间还有1小时时在`Header`中返回`x-refresh-token`:`newToken`
// j := NewJWT("密钥", 2, 1)
// r.USE(JWTAuth(j))
func JWTAuth(j *JWT) gin.HandlerFunc {return func(c *gin.Context) {token := c.Request.Header.Get("Authorization")token = strings.TrimPrefix(token, "Bearer ")claims, err := j.ParseToken(token)if err != nil {response.Fail(c, "Token错误: "+err.Error())c.Abort()return}if time.Since(claims.ExpiresAt.Local()) < j.refreshHours {newToken, err := j.CreateToken(claims.UserClaims)if err != nil {response.Fail(c, "Token刷新错误: "+err.Error())c.Abort()return}c.Header("x-refresh-token", newToken)}c.Set("claims", claims)c.Next()}}func GetUserToken(c *gin.Context) *UserClaims {claims, _ := c.Get("claims")if claims == nil {return &UserClaims{}}return &claims.(*jwtClaims).UserClaims
}type BaseResponse struct {Success      bool   `json:"success"`Data         any    `json:"data"`Message      string `json:"message"`ErrorMessage string `json:"errorMessage"`
}func OkWithData(c *gin.Context, data any) {c.JSON(200, BaseResponse{Success: true, Data: data})
}func OkWithMsg(c *gin.Context, msg string) {c.JSON(200, BaseResponse{Success: true, Message: msg})
}func Fail(c *gin.Context, errMsg string) {c.JSON(200, BaseResponse{Success: false, ErrorMessage: errMsg})
}

main.go

package middlewareimport ("fmt""github.com/gin-gonic/gin"
)func main() {j := NewJWT("密钥", 2, 1)r := gin.Default()r.POST("/login", func(ctx *gin.Context) {// 处理登录逻辑返回token, 前端需讲token存储到localstoragetoken, err := j.CreateToken(UserClaims{UserID: 1, RoleID: 1, UserName: "Leo"})if err != nil {response.Fail(ctx, err.Error())return}response.OkWithData(ctx, gin.H{"token": token})})auth := r.Group("/api")auth.Use(JWTAuth(j))auth.GET("/test", func(ctx *gin.Context) {u := GetUserToken(ctx)response.OkWithMsg(ctx, fmt.Sprintf("用户ID:%d角色ID:%d用户名:%s", u.UserID, u.RoleID, u.UserName))})
}

相关文章:

Gin + Ant Design Pro JWT认证

文章目录 一&#xff1a;介绍二&#xff1a;Gin JWT 后台1. Claims 定义2. 创建和解析Token3. Gin中间件编写4. 辅助函数 三&#xff1a;Ant Design Pro JWT认证四&#xff1a;Gin中间件和使用示范 一&#xff1a;介绍 JWT现在比较流行的认证方式&#xff0c;微服务中使用特别…...

canvas实现图片标注,绘制区域

使用canvas绘制通过多边形标注区域 AI视频项目中需要分析图片&#xff0c;需要前台绘制区域&#xff0c;后端获取坐标然后识别图像&#xff0c;通过canvas 获取点然后连线绘图 HEML代码段 <div class"areaDrawing"><img src"/assets/images/snapPhotos…...

SELECT COUNT(*) 会造成全表扫描吗?

前言 SELECT COUNT(*)会不会导致全表扫描引起慢查询呢&#xff1f; SELECT COUNT(*) FROM SomeTable 网上有一种说法&#xff0c;针对无 where_clause 的 COUNT(*)&#xff0c;MySQL 是有优化的&#xff0c;优化器会选择成本最小的辅助索引查询计数&#xff0c;其实反而性能…...

python考前复习(90题)

文章目录 1.Python特性的是( )。 A. 面向对象 B. 高可移植性 C. 开源、免费 2.临时改变Python语言安装源应当使用的选项是 –index-url 3.Python脚本文件的扩展名为( ) .py 4.安装Python语言的软件包使用的命令是&#xff08; &#xff09; pip install 5 . (单选题)以下哪项是…...

根据SpringBoot Guides完成进行示例学习(详细步骤)

目录 1.打开Spring | Guides官网&#xff0c;或者直接搜索springboot都可 2.选择要学习的内容 3.根据提示的网址&#xff0c;Git到本地 4.将文件用IDEA打开&#xff0c;根据教程完成示例&#xff0c;这里不做细致讲解 5.运行项目 6.在终端查看运行结果 以Scheduling Task…...

waf、yakit和ssh免密登录

WAF安全狗 脏数据适用于所有漏洞绕过waf&#xff0c;但是前提条件垃圾信息必须放在危险信息前&#xff0c;是不能打断原有数据包的结构&#xff0c;不能影响后端对数据包的解析。 以DVWA靶场文件上传为例 新建php文件 上传文件被安全狗拦截 使用bp抓包查看 在数据包Content-…...

【AIGC核心技术剖析】大型语言和视觉助手——LLaVA(论文+源码)

🔥 [新!LLaVA-1.5 在 11 个基准测试上实现了 SoTA,只需对原始 LLaVA 进行简单的修改,利用所有公共数据,在单个 1-A8 节点上在 ~100 天内完成训练,并超越使用数十亿级数据的方法。 LLaVA代表了一种新颖的端到端训练大型多模态模型,结合了视觉编码器和骆马 对于通用的视…...

IBM的WAS简介与基本使用手册

IBM的WAS简介与基本使用手册 1. 基本介绍 WebSphereApplication Server(简称WAS)是IBM的应用服务器 基本结构:单元(cell) ——> 多个节点(node) ——> 多个服务(server) ——> 多个应用(app) 单元是整个分布式网络中一个或多个节点的逻辑分组单元是一个配置概念, 是…...

Deno 快速入门

目录 1、简介 2、安装Deno MacOS下安装 Windows下安装 Linux 下安装 3、创建并运行TypeScript程序 4、内置Web API和Deno命名空间 5、运行时安全 6、导入JavaScript模块 7、远程模块和Deno标准库 8、使用deno.json配置您的项目 9、Node.js API和npm包 10、配置IDE…...

【计算机网络笔记】OSI参考模型基本概念

系列文章目录 什么是计算机网络&#xff1f; 什么是网络协议&#xff1f; 计算机网络的结构 数据交换之电路交换 数据交换之报文交换和分组交换 分组交换 vs 电路交换 计算机网络性能&#xff08;1&#xff09;——速率、带宽、延迟 计算机网络性能&#xff08;2&#xff09;…...

ConnectTimeout和ReadTimeout所代表的意义

ConnectTimeout和ReadTimeout所代表的意义 ConnectTimeout 指的是建立连接所用的时间&#xff0c;适用于网络状况正常的情况下&#xff0c;两端连接所用的时间。在java中&#xff0c;网络状况正常的情况下&#xff0c;例如使用HttpClient或者HttpURLConnetion连接时设置参数c…...

使用Python计算平面多边形间最短距离,数据需要从excel表格中导入

使用Python计算平面多边形间最短距离&#xff0c;数据需要从excel表格中导入&#xff0c; * 多边形种类包括&#xff08;圆形、矩形、六边形、五边形、跑道形/胶囊形&#xff09;&#xff0c; * Python代码需要使用gjk算法进行判断两个多边形间是否重叠&#xff0c; * 如果未重…...

华为数通方向HCIP-DataCom H12-831题库(多选题:1-20)

第01题 如图所示,路由器所有的接口开启OSPF,图中标识的ip地址为设备的Loopback0接口的IP地址,R1、R2,R3的Loopback0通告在区域1,R4的Loopback0通告在区域0、R5的Lopback0通告在区域2,下列哪些IP地址之间可以相互Ping通? A、10.0.3.3和10.0.5.5 B、10.0.4.4和10.0.2.2 …...

CCC数字钥匙设计【NFC】--通过NFC进行车主配对Phase3

1、车主配对流程介绍 车主配对可以通过车内NFC进行&#xff0c;若支持UWB测距&#xff0c;也可以通过蓝牙/UWB进行。通过NFC进行车主配对总共有5个Phase。本文档主要对Phase3进行介绍。 1) Phase0&#xff1a;准备阶段&#xff1b; 2) Phase1&#xff1a;启动流程&#xff1…...

开源OA协同办公系统,集成Flowable流程引擎 可拖拽创建个性表单

源码下载&#xff1a;https://download.csdn.net/download/m0_66047725/88403340 源码下载2&#xff1a; 关注我留言 开源OA协同办公系统&#xff0c;集成Flowable流程引擎 可拖拽创建个性表单。基于RuoYi-VUE版本开发。 1、使用RuoYi-Vue的基础上开发。 2、集成flowable&a…...

为什么嵌入通常优于TF-IDF:探索NLP的力量

塔曼纳 一、说明 自然语言处理&#xff08;NLP&#xff09;是计算机科学的一个领域&#xff0c;涉及人类语言的处理和分析。它用于各种应用程序&#xff0c;例如聊天机器人、情绪分析、语音识别等。NLP 中的重要任务之一是文本分类&#xff0c;我们根据文本的内容将文本分类为不…...

oracle-AWR报告生成方法

AWR报告生成方法 1. 以oracle用户登陆服务器 2. 进入到要保存awr报告的目录 3. 以sysdba身份连接数据库 sqlplus / as sysdba4. 执行生成AWR报告命令 ?/rdbms/admin/awrrpt.sql5. 选择AWR报告的文件格式 6. 选择生成多少天的AWR报告 7. 选择报告的快照起始和结束ID 8. 输入生…...

笙默考试管理系统-MyExamTest----codemirror(37)

笙默考试管理系统-MyExamTest----codemirror&#xff08;36&#xff09; 目录 一、 笙默考试管理系统-MyExamTest 二、 笙默考试管理系统-MyExamTest 三、 笙默考试管理系统-MyExamTest 四、 笙默考试管理系统-MyExamTest 五、 笙默考试管理系统-MyExamTest 笙默考试…...

【Unity3D编辑器拓展】Unity3D的IMGUI、GUI、GUILayout、EditorGUI、EditorGUILayout、OnGUI【全面总结】

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址我的个人博客 大家好&#xff0c;我是佛系工程师☆恬静的小魔龙☆&#xff0c;不定时更新Unity开发技巧&#xff0c;觉得有用记得一键三连哦。 一、前言 在开发中&#xff0c;常常会遇到要使用OnGUI的地方。 也会遇到…...

11. 机器学习 - 评价指标2

文章目录 混淆矩阵F-scoreAUC-ROC 更多内容&#xff1a; 茶桁的AI秘籍 Hi, 你好。我是茶桁。 上一节课&#xff0c;咱们讲到了评测指标&#xff0c;并且在文章的最后提到了一个矩阵&#xff0c;我们就从这里开始。 混淆矩阵 在我们实际的工作中&#xff0c;会有一个矩阵&am…...

C++_核心编程_多态案例二-制作饮品

#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为&#xff1a;煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作饮品基类&#xff0c;提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

深入理解JavaScript设计模式之单例模式

目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式&#xff08;Singleton Pattern&#…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils&#xff1a; ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类&#xff0c;封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz&#xff0c;先构建任务的 JobD…...

使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装

以下是基于 vant-ui&#xff08;适配 Vue2 版本 &#xff09;实现截图中照片上传预览、删除功能&#xff0c;并封装成可复用组件的完整代码&#xff0c;包含样式和逻辑实现&#xff0c;可直接在 Vue2 项目中使用&#xff1a; 1. 封装的图片上传组件 ImageUploader.vue <te…...

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

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

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

【HTML-16】深入理解HTML中的块元素与行内元素

HTML元素根据其显示特性可以分为两大类&#xff1a;块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

IT供电系统绝缘监测及故障定位解决方案

随着新能源的快速发展&#xff0c;光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域&#xff0c;IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选&#xff0c;但在长期运行中&#xff0c;例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...

AI,如何重构理解、匹配与决策?

AI 时代&#xff0c;我们如何理解消费&#xff1f; 作者&#xff5c;王彬 封面&#xff5c;Unplash 人们通过信息理解世界。 曾几何时&#xff0c;PC 与移动互联网重塑了人们的购物路径&#xff1a;信息变得唾手可得&#xff0c;商品决策变得高度依赖内容。 但 AI 时代的来…...

JVM虚拟机:内存结构、垃圾回收、性能优化

1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...