【gin】中间件使用之jwt身份认证和Cors跨域,go案例

打印 上一主题 下一主题

主题 982|帖子 982|积分 2946

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
Gin-3 中间件编程及 JWT 身份认证

1. Gin 中间件概述

中间件是处置惩罚 HTTP 请求的函数,可以在请求到达路由处置惩罚函数之前或之后对请求进行处置惩罚。
在 Gin 框架中,中间件常用于处置惩罚日志记录、身份验证、权限控制等功能。
  1. router := gin.Default()
  2. router.Use(middleware) // 使用中间件
复制代码
中间件可以通过 Use 方法进行添加,并且可以用于全部路由特定路由组
2. JWT 简介

https://github.com/golang-jwt/jwt
JSON Web Token(JWT)是一种用于认证和授权的标准。JWT 包罗三个部分:

  • 头部 (Header)
  • 载荷 (Payload)
  • 署名 (Signature)
  1. JWT = Base64UrlEncode(HEADER) + "." + Base64UrlEncode(PAYLOAD) + "." + Base64UrlEncode(SIGNATURE)
复制代码
JWT 的优点是自包罗,它在用户和服务之间转达信息时不依赖于存储。
由于 JWT 包罗全部须要的用户信息,服务端不需要保持用户的状态。
3. Gin 中的 JWT 身份认证明现

在 Gin 中实现 JWT 身份认证主要包罗以下步骤:

  • 天生 JWT Token:登录时天生 JWT Token。
  • 验证 JWT Token:通过中间件验证请求中的 Token。
  • 访问受掩护路由:只有验证通过的用户才华访问受掩护的路由。
3.1 JWT 天生与验证函数

通过以下代码,您可以天生和验证 JWT Token:
  1. package jwt_plugin
  2. import "github.com/golang-jwt/jwt/v5"
  3. var key = "abcdefg123" // 用于加密和解密的密钥
  4. // 数据结构,存储用户信息和标准声明
  5. type Data struct {
  6.     Name   string `json:"name"`
  7.     Age    int    `json:"age"`
  8.     Gender int    `json:"gender"`
  9.     jwt.RegisteredClaims
  10. }
  11. // 生成 JWT Token
  12. func Sign(data jwt.Claims) (string, error) {
  13.     token := jwt.NewWithClaims(jwt.SigningMethodHS256, data)
  14.     sign, err := token.SignedString([]byte(key))
  15.     if err != nil {
  16.         return "", err
  17.     }
  18.     return sign, nil
  19. }
  20. // 验证 JWT Token
  21. func Verify(sign string, data jwt.Claims) error {
  22.     _, err := jwt.ParseWithClaims(sign, data, func(token *jwt.Token) (any, error) {
  23.         return []byte(key), nil
  24.     })
  25.     return err
  26. }
复制代码
天生 JWT Token 时,我们会使用 Sign 函数,验证时使用 Verify 函数。
Sign 函数会将用户信息(载荷)和署名一起返回,Verify 函数用于验证 JWT Token 是否有效。
3.2 登录接口实现

用户登录时,通过 Login 函数天生 JWT Token,并返回给客户端。
  1. package login
  2. import (
  3.     "github.com/gin-gonic/gin"
  4.     "golang13-gin/jwt_plugin"
  5.     "net/http"
  6.     "time"
  7. )
  8. func Login(c *gin.Context) {
  9.     // 用户信息及 JWT 载荷
  10.     data := jwt_plugin.Data{
  11.         Name:   "nick",
  12.         Age:    18,
  13.         Gender: 1,
  14.         RegisteredClaims: jwt.RegisteredClaims{
  15.             ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour)),
  16.             IssuedAt:  jwt.NewNumericDate(time.Now()),
  17.             NotBefore: jwt.NewNumericDate(time.Now()),
  18.         },
  19.     }
  20.    
  21.     // 生成 JWT Token
  22.     sign, err := jwt_plugin.Sign(data)
  23.     if err != nil {
  24.         c.JSON(http.StatusInternalServerError, gin.H{
  25.             "error": err.Error(),
  26.         })
  27.         return
  28.     }
  29.     // 返回 JWT Token
  30.     c.JSON(http.StatusOK, gin.H{
  31.         "access_token": sign,
  32.     })
  33. }
复制代码
登录成功后,系统会返回一个包罗用户信息和有效期的 JWT Token。
3.3 JWT 身份验证中间件

  1. package middleware
  2. import (
  3.     "github.com/gin-gonic/gin"
  4.     "golang13-gin/jwt_plugin"
  5.     "net/http"
  6. )
  7. func Auth() gin.HandlerFunc {
  8.     return func(c *gin.Context) {
  9.         accessToken := c.Request.Header.Get("access_token") // 获取请求头中的 Token
  10.         data := &jwt_plugin.Data{}
  11.         err := jwt_plugin.Verify(accessToken, data) // 验证 Token
  12.         if err != nil {
  13.             c.JSON(http.StatusForbidden, gin.H{
  14.                 "error": "身份认证失败",
  15.             })
  16.             c.Abort() // 中止请求
  17.         }
  18.         c.Set("auth_info", data) // 将用户信息存储在上下文中
  19.         c.Next() // 继续后续处理
  20.     }
  21. }
复制代码
身份验证中间件 Auth 会从请求头中提取 JWT Token 并进行验证。假如验证失败,返回 403 错误;否则将用户信息存储到上下文,供后续路由使用。
4. CORS 中间件

CORS(跨域资源共享)答应服务器指定哪些源(Origin)可以访问资源。以下是设置 CORS 中间件的代码:
  1. package middleware
  2. import (
  3.     "github.com/gin-contrib/cors"
  4.     "github.com/gin-gonic/gin"
  5. )
  6. func Cors() gin.HandlerFunc {
  7.     return cors.New(cors.Config{
  8.         AllowAllOrigins: true,
  9.         AllowHeaders: []string{
  10.             "Origin", "Content-Length", "Content-Type",
  11.         },
  12.         AllowMethods: []string{
  13.             "GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS",
  14.         },
  15.     })
  16. }
复制代码
CORS 中间件配置答应来自任何来源的请求,并且可以处置惩罚指定的 HTTP 方法和头部。
5. 路由初始化与中间件使用

在 Gin 中,可以通过 Use 方法将中间件添加到路由组中,以下是一个例子:
  1. func InitRoutes(r *gin.Engine) {   
  2.     api := r.Group("/api")   
  3.     api.Use(middleware.Cors(), middleware.Auth()) // 使用 CORS 和 JWT 验证中间件
  4.     InitCourse(api)   
  5.     InitUser(api)   
  6.     InitUpload(api)   
  7.     notAuthApi := r.Group("/api")   
  8.     notAuthApi.Use(middleware.Cors())   
  9.     InitLogin(notAuthApi) // 不需要身份验证的路由   
  10. }
复制代码
总结

概念形貌代码示例Gin 中间件中间件是一个函数,用来处置惩罚 HTTP 请求。在请求进入路由处置惩罚函数之前或之后,实行某些操纵。router.Use(middleware)JWT (JSON Web Token)一种用于认证和授权的标准格式,通过三个部分构成:头部、载荷和署名。它具有自包罗特性,可以在分布式系统中使用。token := jwt.NewWithClaims(jwt.SigningMethodHS256, data)JWT 天生通过载荷和密钥天生 JWT Token。sign, err := jwt_plugin.Sign(data)JWT 验证通过 Token 验证用户身份,确保请求的合法性。err := jwt_plugin.Verify(accessToken, data)身份认证中间件在请求到达目的路由之前,验证请求中的 JWT Token,确保只有通过验证的请求才华继续处置惩罚。func Auth() gin.HandlerFunc { return func(c *gin.Context) { ... } }CORS 中间件办理欣赏器跨域问题,答应差别域的请求访问服务器资源。func Cors() gin.HandlerFunc { return cors.New(cors.Config{ AllowAllOrigins: true }) }路由组将具有共同前缀的路由放在一个组中,方便统一管理和中间件的应用。api := r.Group("/api")JWT 载荷JWT 中的数据部分,包罗用户信息和其他元数据。可以自界说内容,也可以使用预界说的注册声明(如过期时间)。RegisteredClaims: jwt.RegisteredClaims{ ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour)) }路由配置界说与中间件、请求处置惩罚函数相关的路由。InitLogin(notAuthApi) 表格表明:

  • Gin 中间件 是一类用于在路由处置惩罚函数实行前或后处置惩罚请求的函数,常见的中间件包罗身份认证、中间件控制等。
  • JWT 是一种 JSON 格式的认证方式,包罗头部、载荷和署名,实用于分布式系统,办理了服务端无状态的问题。
  • JWT 天生和验证 是通过特定的密钥和载荷数据天生的,可以通过库函数轻松实现天生和验证操纵。
  • 身份认证中间件 通过在请求处置惩罚中拦截请求并验证 JWT Token 是否有效来确保用户身份的合法性。
  • CORS 中间件 答应差别来源的客户端发起请求,办理跨域问题,常见于前后端分离的应用场景。
  • 路由组 可以帮助组织和管理具有共同特性的路由,通过给路由组添加中间件,使得多个路由共享特定的功能。
  • JWT 载荷 中的数据部分,存储的是用户信息以及与身份认证相关的信息(如过期时间等)。

JWT载荷

JWT 载荷部分是什么,是否无关紧急?
JWT 的载荷部分是存储在 Token 中的实际信息,它包罗了 声明(claims),这些声明通常用于存储用户信息、权限、Token 的有效期等。
JWT 载荷部分包罗以下几种范例的声明:


  • 注册声明(Registered Claims):如 exp(过期时间)、iat(签发时间)、sub(主题)等。
  • 公共声明(Public Claims):可以自界说,用于表示用户信息或其他数据。
  • 私有声明(Private Claims):由双方约定用于转达的信息。
    是否无关紧急?
假如只是需要转达一个简单的标识符(如用户 ID),那么可以简化载荷部分。
但通常,JWT 的载荷是不可或缺的,因为它包罗了 Token 的有效期、权限等紧张信息。
假如载荷部分为空或缺少须要的字段,Token 的使用代价将大大低落。

https://github.com/0voice

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

耶耶耶耶耶

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表