go jwt 用户登录和返回用户信息 token ----important!!!
1.每一行代码都有详细注释,解释了其功能和作用。这些注释可以帮助你理解代码如何工作,特别是在处理用户登录、生成 JWT、验证 JWT 和返回用户信息的过程中。
package main // 指定这个文件是一个可执行程序import ("fmt" // 标准库包,用于格式化字符串和输出到控制台"github.com/dgrijalva/jwt-go" // 第三方库,用于处理 JWT"github.com/gin-gonic/gin" // 第三方库,用于构建 Web API"net/http" // 标准库包,提供 HTTP 客户端和服务器实现"time" // 标准库包,提供时间的基本操作
)var jwtKey = []byte("your_secret_key") // 用于签名 JWT 的密钥// Claims 定义了包含用户信息的自定义 JWT 结构
type Claims struct {Identity int `json:"identity"` // 用户 IDjwt.StandardClaims // 域包含 JWT 标准的声明,如过期时间、发布者等
}func main() {r := gin.Default() // 创建一个默认的 Gin 路由器实例r.POST("/login", login) // 定义 POST 方法的 /login 路由,处理用户登录请求r.GET("/user", authenticate, getUserId) // 定义 GET 方法的 /user 路由,先进行用户验证再获取用户 ID// 生成一个有效的 JWT token 并打印出来generateAndPrintToken()r.Run(":8080") // 启动服务器,监听端口 8080
}// login 处理用户登录请求,生成 JWT token 并返回给客户端
func login(c *gin.Context) {identity := 135 // 模拟用户的 ID// 创建包含用户 ID 和过期时间的 JWT claimsexpirationTime := time.Now().Add(5 * time.Minute) // 设置 token 的过期时间为当前时间的 5 分钟后claims := &Claims{Identity: identity, // 设置用户的 IDStandardClaims: jwt.StandardClaims{ExpiresAt: expirationTime.Unix(), // 设置 JWT 的过期时间},}// 创建 JWT tokentoken := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) // 使用 HS256 签名方法创建 JWTtokenString, err := token.SignedString(jwtKey) // 使用密钥签名生成 JWTif err != nil {c.JSON(http.StatusInternalServerError, gin.H{"error": "无法创建token"}) // 如果签名失败,返回 500 错误return}// 返回 token 给客户端c.JSON(http.StatusOK, gin.H{"token": tokenString})
}// authenticate 中间件,验证请求是否携带有效的 JWT token
func authenticate(c *gin.Context) {tokenString := c.GetHeader("Authorization") // 从请求头中获取 Authorization 字段的值// 解析 tokenclaims := &Claims{}token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {return jwtKey, nil // 返回用于签名的密钥})if err != nil || !token.Valid { // 如果解析或验证失败c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "无效的token"}) // 中止请求并返回 401 错误return}// 将 claims 保存到上下文中,以便后续处理使用c.Set("claims", claims)c.Next() // 继续处理下一个处理函数
}// getUserId 从上下文中提取用户 ID 并返回给客户端
func getUserId(c *gin.Context) {data := ExtractClaims(c) // 从上下文中提取 claimsif data == nil {fmt.Println(fmt.Sprintf("%s [WARNING] %s %s GetUserId 缺少 identity", time.Now().Format(time.RFC3339), c.Request.Method, c.Request.URL.Path))c.JSON(http.StatusUnauthorized, gin.H{"error": "无法获取用户ID"}) // 如果没有提取到 claims,返回 401 错误return}//identity := data.Identity // 获取用户 ID//c.JSON(http.StatusOK, gin.H{"userId": identity}) // 返回用户 ID 给客户端c.JSON(http.StatusOK, gin.H{"data": data}) // 返回用户 ID 给客户端
}// ExtractClaims 从上下文中提取 JWT claims
func ExtractClaims(c *gin.Context) *Claims {claims, exists := c.Get("claims") // 从上下文中获取 claimsif !exists {return nil // 如果 claims 不存在,返回 nil}return claims.(*Claims) // 返回 claims
}// generateAndPrintToken 生成一个新的 JWT token 并打印到控制台
func generateAndPrintToken() {identity := 135 // 模拟用户的 ID// 创建包含用户 ID 和过期时间的 JWT claimsexpirationTime := time.Now().Add(5 * time.Minute) // 设置 token 的过期时间为当前时间的 5 分钟后claims := &Claims{Identity: identity, // 设置用户的 IDStandardClaims: jwt.StandardClaims{ExpiresAt: expirationTime.Unix(), // 设置 JWT 的过期时间},}// 创建 JWT tokentoken := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) // 使用 HS256 签名方法创建 JWTtokenString, err := token.SignedString(jwtKey) // 使用密钥签名生成 JWTif err != nil {fmt.Println("无法创建token:", err) // 如果签名失败,打印错误return}fmt.Println("生成的token:", tokenString) // 打印生成的 token
}
2.好的,我们可以将代码分为两个部分:一个处理用户登录,并生成 JWT token;另一个验证 JWT token 并返回用户信息。以下是详细分类和注释:
(1)用户登录部分
package main // 指定这个文件是一个可执行程序import ("fmt" // 标准库包,用于格式化字符串和输出到控制台"net/http" // 标准库包,提供 HTTP 客户端和服务器实现"time" // 标准库包,提供时间的基本操作"github.com/dgrijalva/jwt-go" // 第三方库,用于处理 JWT"github.com/gin-gonic/gin" // 第三方库,用于构建 Web API
)var jwtKey = []byte("your_secret_key") // 用于签名 JWT 的密钥// Claims 定义了包含用户信息的自定义 JWT 结构
type Claims struct {Identity int `json:"identity"` // 用户 IDjwt.StandardClaims // 域包含 JWT 标准的声明,如过期时间、发布者等
}func main() {r := gin.Default() // 创建一个默认的 Gin 路由器实例r.POST("/login", login) // 定义 POST 方法的 /login 路由,处理用户登录请求r.GET("/user", authenticate, getUserId) // 定义 GET 方法的 /user 路由,先进行用户验证再获取用户 ID// 生成一个有效的 JWT token 并打印出来generateAndPrintToken()r.Run(":8080") // 启动服务器,监听端口 8080
}// 用户登录部分:处理用户登录请求,生成 JWT token 并返回给客户端
func login(c *gin.Context) {identity := 135 // 模拟用户的 ID// 创建包含用户 ID 和过期时间的 JWT claimsexpirationTime := time.Now().Add(5 * time.Minute) // 设置 token 的过期时间为当前时间的 5 分钟后claims := &Claims{Identity: identity, // 设置用户的 IDStandardClaims: jwt.StandardClaims{ExpiresAt: expirationTime.Unix(), // 设置 JWT 的过期时间},}// 创建 JWT tokentoken := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) // 使用 HS256 签名方法创建 JWTtokenString, err := token.SignedString(jwtKey) // 使用密钥签名生成 JWTif err != nil {c.JSON(http.StatusInternalServerError, gin.H{"error": "无法创建token"}) // 如果签名失败,返回 500 错误return}// 返回 token 给客户端c.JSON(http.StatusOK, gin.H{"token": tokenString})
}// generateAndPrintToken 生成一个新的 JWT token 并打印到控制台
// 仅用于辅助测试,在实际应用中可能不会使用
func generateAndPrintToken() {identity := 135 // 模拟用户的 ID// 创建包含用户 ID 和过期时间的 JWT claimsexpirationTime := time.Now().Add(5 * time.Minute) // 设置 token 的过期时间为当前时间的 5 分钟后claims := &Claims{Identity: identity, // 设置用户的 IDStandardClaims: jwt.StandardClaims{ExpiresAt: expirationTime.Unix(), // 设置 JWT 的过期时间},}// 创建 JWT tokentoken := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) // 使用 HS256 签名方法创建 JWTtokenString, err := token.SignedString(jwtKey) // 使用密钥签名生成 JWTif err != nil {fmt.Println("无法创建token:", err) // 如果签名失败,打印错误return}fmt.Println("生成的token:", tokenString) // 打印生成的 token
}
(2)返回用户信息部分
// authenticate 中间件,验证请求是否携带有效的 JWT token
// 适用于返回用户信息的部分
func authenticate(c *gin.Context) {tokenString := c.GetHeader("Authorization") // 从请求头中获取 Authorization 字段的值// 解析 tokenclaims := &Claims{}token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {return jwtKey, nil // 返回用于签名的密钥})if err != nil || !token.Valid { // 如果解析或验证失败c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "无效的token"}) // 中止请求并返回 401 错误return}// 将 claims 保存到上下文中,以便后续处理使用c.Set("claims", claims)c.Next() // 继续处理下一个处理函数
}// getUserId 从上下文中提取用户 ID 并返回给客户端
// 适用于返回用户信息的部分
func getUserId(c *gin.Context) {data := ExtractClaims(c) // 从上下文中提取 claimsif data == nil {fmt.Println(fmt.Sprintf("%s [WARNING] %s %s GetUserId 缺少 identity", time.Now().Format(time.RFC3339), c.Request.Method, c.Request.URL.Path))c.JSON(http.StatusUnauthorized, gin.H{"error": "无法获取用户ID"}) // 如果没有提取到 claims,返回 401 错误return}identity := data.Identity // 获取用户 IDc.JSON(http.StatusOK, gin.H{"userId": identity}) // 返回用户 ID 给客户端
}// ExtractClaims 从上下文中提取 JWT claims
// 适用于返回用户信息的部分
func ExtractClaims(c *gin.Context) *Claims {claims, exists := c.Get("claims") // 从上下文中获取 claimsif !exists {return nil // 如果 claims 不存在,返回 nil}return claims.(*Claims) // 返回 claims
}
3.测试:
获取token:

使用生成的 JWT token 测试
在 Postman 中,按照以下步骤:
- 创建一个新的
GET请求。 - 设置 URL 为
http://localhost:8080/user。 - 在请求头中添加一个新的头字段
Authorization,值为你在上面生成的 JWT token。 - 点击 "Send" 按钮。
你将会收到包含用户 ID 的 JSON 响应。

相关文章:
go jwt 用户登录和返回用户信息 token ----important!!!
1.每一行代码都有详细注释,解释了其功能和作用。这些注释可以帮助你理解代码如何工作,特别是在处理用户登录、生成 JWT、验证 JWT 和返回用户信息的过程中。 package main // 指定这个文件是一个可执行程序import ("fmt" …...
OpenCV高级图形用户界面(12)用于更改指定窗口的大小函数resizeWindow()的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 cv::resizeWindow() 函数用于更改指定窗口的大小。这使得你可以根据需要调整窗口的宽度和高度。 注释 指定的窗口大小是指图像区域的大小。工具栏…...
babylonjs shader学习之copy shadertoy案例
shadertoy案例: 准备 const onSceneReady (scene: Scene) > {const light new HemisphericLight(light, new Vector3(0, 1, 0), scene);light.intensity 0.7;Effect.ShadersStore[planeMatVertexShader] precision highp float;attribute vec3 position;attr…...
Leetcode 1137. 第 N 个泰波那契数
原题链接:Leetcode 1137. 第 N 个泰波那契数 代码1: class Solution { public:int a[40];int tribonacci(int n) {a[0]0;a[1]1;a[2]1;if(n<1) return n;if(a[n]) return a[n];a[n]tribonacci(n-1)tribonacci(n-2)tribonacci(n-3);return a[n];} };代…...
Rust 语言持续崛起,即将冲击 TIOBE 指数前十,能否成为编程语言新王者?
Rust 语言持续崛起,即将冲击 TIOBE 指数前十,能否成为编程语言新王者? 2024 年 10 月,全球编程语言 TIOBE 排行榜再次更新,各大编程语言在各自领域中继续发挥着独特的优势。官方的标题是: Rust排名稳步攀升…...
Linux 手撕线程池
前言 线程池 是 池化技术 中很典型的一个,它旨在高效的管理和复用线程资源!在现在的计算机体系中,线程是执行任务(调度)的基本单位。然而,频繁的创建和销毁线程也会带来较大的开销,包括系统资源…...
[Unity Demo]从零开始制作空洞骑士Hollow Knight第十五集:制作更多地图,更多敌人,更多可交互对象
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、第一个代表性场景 1.制作更多敌人2.制作更多可交互对象二、第二个代表性场景 1.制作更多敌人2.制作更多可交互对象三、第三个代表性场景 1.制作更多敌人2.制…...
在Openshift上安装MetalLB
1.部署MetalLB Operator 2.部署AddressPool addresses 必须和ocp节点在同一网段 apiVersion: metallb.io/v1beta1 kind: AddressPool metadata:name: metallb-ipaddressnamespace: metallb-system spec:addresses:- 192.168.1.51-192.168.1.60- 192.168.1.61-192.168.1.70aut…...
mysql其他对象
一、存储引擎 mysql的存储引擎包括: InnoDB,MyISAM,Memory(Heap),Archive,CSV,NDB Cluster 常用的只有前两个。 InnoDB与MyISAM的区别: InnoDB 简介:Inn…...
英语单词之社会生活之聚会
一些关于聚会的单词和短语 句子 English中文What’s the plan?计划是什么?I’m going out with some friends.我要跟几个朋友一起出去。I don’t really feel like going out.我不是很想出去。What time suits you ?你什么时间合适?Where shall we m…...
Qt - 地图相关 —— 1、加载百度在线地图(附源码)
效果图 开始加载地图 1、百度地图开发者网站中注册,获取密钥 2、进入开发文档中 将下图内容保存到本地文件中,文件名为"index.html"文件即可。接着将内容中的“您的密钥”改为刚刚创建应用出来的AK密钥即可。 然后双击打开若在浏览器中正常看到下图右侧地图则说明没…...
Elasticsearch 简单使用
Elasticsearch 安装和基本操作 一、引言 Elasticsearch 是一个基于 Lucene 构建的开源分布式搜索引擎,提供了实时的搜索和数据分析能力。它广泛应用于日志分析、全文搜索、数据可视化等场景。本文将详细介绍 Elasticsearch 的安装步骤及基本操作,包括索…...
基于SpringBoot+Vue+uniapp微信小程序的垃圾分类系统的详细设计和实现(源码+lw+部署文档+讲解等)
项目运行截图 技术框架 后端采用SpringBoot框架 Spring Boot 是一个用于快速开发基于 Spring 框架的应用程序的开源框架。它采用约定大于配置的理念,提供了一套默认的配置,让开发者可以更专注于业务逻辑而不是配置文件。Spring Boot 通过自动化配置和约…...
基于深度学习的车辆车型检测识别系统(YOLOV5)
界面图: 项目简介: 网络:深度学习网络 yoloV5 软件:PycharmAnaconda 环境:python3.8 opencv PyQt5 torch1.9 文件:训练集8000张图片 测试集1000张图片 系统包含所有文件夹 环境文件 UI文件 功能&a…...
Java开发中知识点整理
正则表达式 测试网址 Git 分支和主分支有冲突 先checkout origin/分支把origin/master pull进本地分支 修改冲突MergeCommit and Push...
【css-在一个元素中设置font-size和实际渲染字体大小不一致】
首先,这个不是bug,是Chromium内核提高移动端文本可读性的一个特性,叫做这个特性被称做「Text Autosizer」,又称「Font Boosting」、「Font Inflation」 解决方案: 使用-webkit-text-size-adjust 给元素设置 -webkit-te…...
LabVIEW提高开发效率技巧----用户权限控制
在LabVIEW开发中,用户权限控制是一个重要的设计模块,尤其在多用户系统中,它可以确保数据安全并控制不同用户的操作权限。为了实现用户权限控制,可以通过角色与权限管理模块来进行设计和实施。以下将从多个角度详细说明如何在LabVI…...
如何快速学会盲打
今天就来给大家分享一下如何快速学会盲打 盲打的基本方法和步骤 手指放置:将双手放在键盘上,左手食指放在F键上,右手食指放在J键上,其他手指分别放在相邻的键位上。熟悉键盘布局:学习26个字母的位置,以及…...
如何通过外链组合套餐提升外贸网站的整体表现?
在SEO优化中,单一的外链形式很难覆盖所有需求,特别是对于那些竞争激烈的行业。通过高低搭配的外链组合套餐成为越来越多企业的选择 简单来说,外链组合套餐是将不同质量、不同类型的外链进行合理搭配,从而最大化地提升网站的多维度…...
MySQL—事务
目录 1.事务的简介: 2.使用事务 2.1 开启事务 2.2 自动提交 2.3 使用范围 2.4 事务的属性 1.事务的简介: 介绍事务之前,我们先来看一个经典的场景:银行转账。 假如a想要把自己的账户上的10万块钱转到b账户上,这…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...
stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
css实现圆环展示百分比,根据值动态展示所占比例
代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...
《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
React第五十七节 Router中RouterProvider使用详解及注意事项
前言 在 React Router v6.4 中,RouterProvider 是一个核心组件,用于提供基于数据路由(data routers)的新型路由方案。 它替代了传统的 <BrowserRouter>,支持更强大的数据加载和操作功能(如 loader 和…...
dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...
SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...
基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...
初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...
