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 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误
HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...

AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...

USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...