go jwt 用户登录和返回用户信息 token ----important!!!

embedded/2024/10/19 15:32:53/

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 中,按照以下步骤:

  1. 创建一个新的 GET 请求。
  2. 设置 URL 为 http://localhost:8080/user
  3. 在请求头中添加一个新的头字段 Authorization,值为你在上面生成的 JWT token
  4. 点击 "Send" 按钮。

你将会收到包含用户 ID 的 JSON 响应。


http://www.ppmy.cn/embedded/128773.html

相关文章

Linux中安装gcc g++

在线安装 #Ubuntu sudo apt update #更新本地的软件下载列表, 得到最新的下载地址 sudo apt install gcc g#centos sudo yum update sudo yum install gcc g之所以更新下载列表,是因为这样可以下载最新的gcc g 以支持c11 两种方法查看gcc g版本 gcc -v gcc --versiong -v …

用于病理图像诊断的跨尺度多实例学习|文献速递-基于深度学习的医学影像分类,分割与多模态应用

Title 题目 Cross-scale multi-instance learning for pathological image diagnosis 用于病理图像诊断的跨尺度多实例学习 01 文献速递介绍 病理学是诊断炎症性肠病(如克罗恩病)的金标准(Gubatan等,2021;Yeshi等…

【网络安全】IDOR与JWT令牌破解相结合,实现编辑、查看和删除数万帐户

未经许可,不得转载。 文章目录 前言漏洞1漏洞2修复建议在今年4月17日,笔者发过一篇关于 JWT 的文章,未学习过或稍有遗忘的朋友可以点击跳转:【网络安全 | 密码学】JWT基础知识及攻击方式详析 现分享一篇与 JWT 有关的漏洞挖掘案例。 前言 我在某公共漏洞奖励计划的应用程…

【热门】用ChatGPT做智慧农业云平台——农业ERP管控系统

随着科技的进步,原有农业种植方式已经不能满足社会发展的需要,必须对传统的农业进行技术更新和改造。经过多年的实践,人们总结出一种新的种植方法——温室农业,即“用人工设施控制环境因素,使作物获得最适宜的生长条件,从而延长生产季节,获得最佳的产出”。这种农业生产方式…

linux git submodule 需要输入密码的问题

1. 使用git submodule update --init --recursive 命令拉取submodule的时候 2. 提示需要输入密码 3. 打开项目的gitlab地址,点击右上角我的profile,点击左边的SSH-keys 4. ssh-keygen -t ed25519 -C xx 生成一个pubkey 5. cat /root/.ssh/id_ed25519.pub 6. 拷…

LeetCode-3191 使二进制数组全部等于1的最少操作次数

又来到了今天的每日一题,距离上次更新每日一题得有十天了。 主要原因是这十天的题要么简单到爆,要么难到爆,再要么就是最近学校安排实训,时间比较紧。 废话不多说,来看看今天的题目。 题目很简单,就是给个…

【从零到一的笔试突破】——day1笔试巅峰(6道笔试题)ACM模式让笔试更有感觉

文章目录 数字统计(数学模拟)两个数组的交集(哈希)点击消除(栈)牛牛的快递(模拟)最小花费爬楼梯(动态规划)数组中两个字符串的最小距离(滑动窗口o…

使用RNN、LSTM和Transformer进行时间序列预测

文章目录 1 RNN & LSTMRNN结构LSTM结构样本和标签 2 Transformertransformer结构位置编码 1 RNN & LSTM RNN结构 LSTM结构 代码(使用CPU): import numpy as np import torch from matplotlib import pyplot as plt from torch impo…