golang jwt鉴权的实现流程

 更新时间:2025年02月17日 09:24:14   作者:醒醒a  
本文主要介绍了golang jwt鉴权的实现流程,包含生成JWT令牌、客户端存储和发送JWT令牌、服务端验证JWT令牌等,具有一定的参考价值,感兴趣的可以了解一下

JWT(JSON Web Token)是一种用于在网络应用环境间传递声明(Claims)的无状态、独立、紧凑和独立的信息格式。以下是 JWT 进行鉴权的基本流程:

1. 用户登录

用户通过用户名和密码登录系统,系统验证用户身份。

2. 生成 JWT 令牌

系统验证用户身份成功后,生成一个 JWT 令牌。JWT 令牌通常包含以下部分:

  • Header(头部):包含令牌的类型(通常是 JWT)和使用的签名算法(如 HMAC-SHA256)。

  • Payload(载荷):包含声明(Claims),这些声明可以是用户 ID、角色、过期时间等。

  • Signature(签名):用于验证 JWT 的完整性和真实性。

3. 返回 JWT 令牌

系统将生成的 JWT 令牌返回给客户端(通常是浏览器或移动应用)。

4. 客户端存储 JWT 令牌

客户端收到 JWT 令牌后,通常会将其存储在本地存储(如 localStorage 或 sessionStorage)或 Cookie 中。

5. 客户端发送请求

客户端在后续的请求中,将 JWT 令牌放在 HTTP 请求头的 Authorization 字段中,格式通常为 Bearer <token>

6. 服务端验证 JWT 令牌

服务端接收到请求后,从 Authorization 请求头中提取 JWT 令牌,并进行验证:

  • 验证签名:使用与生成 JWT 时相同的密钥验证 JWT 的签名是否有效。

  • 验证过期时间:检查 JWT 的过期时间是否已过。

  • 验证其他声明:根据需要验证其他声明,如用户角色、权限等。

7. 处理请求

如果 JWT 令牌验证通过,服务端处理请求并返回响应。如果验证失败,返回错误响应(如 401 Unauthorized)。

示例代码

生成 JWT 令牌(服务端)

package main

import (
    "fmt"
    "time"
    "github.com/golang-jwt/jwt"
)

// 自定义 Claims
type CustomClaims struct {
    UserID   string `json:"user_id"`
    Role     string `json:"role"`
    jwt.StandardClaims
}

func main() {
    // 自定义 Claims
    claims := CustomClaims{
        UserID: "12345",
        Role:   "admin",
        StandardClaims: jwt.StandardClaims{
            ExpiresAt: time.Now().Add(24 * time.Hour).Unix(),
            Issuer:    "myapp",
        },
    }

    // 密钥
    jwtSecret := "mysecretkey"

    // 创建 JWT 令牌
    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)

    // 使用密钥签名并生成字符串形式的 JWT 令牌
    tokenString, err := token.SignedString([]byte(jwtSecret))
    if err != nil {
        fmt.Println("生成令牌失败:", err)
        return
    }

    fmt.Println("生成的 JWT 令牌:", tokenString)
}

验证 JWT 令牌(服务端)

package main

import (
    "fmt"
    "net/http"
    "strings"
    "github.com/golang-jwt/jwt"
)

// 自定义 Claims
type CustomClaims struct {
    UserID   string `json:"user_id"`
    Role     string `json:"role"`
    jwt.StandardClaims
}

func handler(w http.ResponseWriter, r *http.Request) {
    // 获取 Authorization 请求头
    authHeader := r.Header.Get("Authorization")

    // 检查 Authorization 请求头是否存在
    if authHeader == "" {
        http.Error(w, "Missing Authorization header", http.StatusUnauthorized)
        return
    }

    // 提取 JWT 令牌
    tokenString := strings.TrimPrefix(authHeader, "Bearer ")

    // 验证 JWT 令牌
    token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
        // 提供签名密钥
        return []byte("mysecretkey"), nil
    })

    if err != nil {
        http.Error(w, "Invalid token", http.StatusUnauthorized)
        return
    }

    if !token.Valid {
        http.Error(w, "Invalid token", http.StatusUnauthorized)
        return
    }

    // 处理请求
    fmt.Fprintf(w, "Hello, World!")
}

func main() {
    http.HandleFunc("/api/data", handler)
    http.ListenAndServe(":8080", nil)
}

可以将验证jwt令牌的方法定义为中间件(Middleware),通过Use方法注册到gin中,应用于所有路由。gin的中间件在请求处理流程中被调用,可以对请求进行预处理、修改请求或响应,甚至可以终止请求的处理。中间件在 Gin 中非常常用,可以用于实现诸如身份验证、日志记录、请求限制等功能。

示例代码:

package main

import (
    "github.com/gin-gonic/gin"
    "github.com/golang-jwt/jwt"
    "strings"
)

// 自定义 Claims
type CustomClaims struct {
    UserID   string `json:"user_id"`
    Role     string `json:"role"`
    jwt.StandardClaims
}

// Auth 返回一个 Gin 中间件函数
func Auth() gin.HandlerFunc {
    return func(c *gin.Context) {
        // 获取 Authorization 请求头
        authHeader := c.GetHeader("Authorization")

        // 检查 Authorization 请求头是否存在
        if authHeader == "" {
            c.JSON(401, gin.H{"error": "Missing Authorization header"})
            c.Abort()
            return
        }

        // 提取 JWT 令牌
        tokenString := strings.TrimPrefix(authHeader, "Bearer ")

        // 验证 JWT 令牌
        token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
            // 提供签名密钥
            return []byte("mysecretkey"), nil
        })

        if err != nil {
            c.JSON(401, gin.H{"error": "Invalid token"})
            c.Abort()
            return
        }

        if !token.Valid {
            c.JSON(401, gin.H{"error": "Invalid token"})
            c.Abort()
            return
        }

        // 如果验证通过,继续处理请求
        c.Next()
    }
}

func main() {
    r := gin.Default()

    // 使用 Auth 中间件
    r.Use(Auth())

    r.GET("/api/data", func(c *gin.Context) {
        c.JSON(200, gin.H{"message": "Hello, World!"})
    })

    r.Run(":8080")
}

到此这篇关于golang jwt鉴权的实现流程的文章就介绍到这了,更多相关golang jwt鉴权内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家! 

相关文章

  • Go语言中的流程控制结构和函数详解

    Go语言中的流程控制结构和函数详解

    这篇文章主要介绍了Go语言中的流程控制结构和函数详解,本文详细讲解了if、goto、for、switch等控制语句,同时对函数相关知识做了讲解,需要的朋友可以参考下
    2014-10-10
  • 简单聊聊Golang中Flag包的具体使用

    简单聊聊Golang中Flag包的具体使用

    flag 包是 Go 语言标准库中的一个包,用于解析命令行参数,这篇文章主要来和大家简单聊聊Golang中Flag包的具体使用,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-05-05
  • golang使用http client发起get和post请求示例

    golang使用http client发起get和post请求示例

    这篇文章主要介绍了golang使用http client发起get和post请求示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-02-02
  • go语言单例模式(Singleton)实例分析

    go语言单例模式(Singleton)实例分析

    这篇文章主要介绍了go语言单例模式(Singleton),实例分析了单例模式的原理与Go语言的实现技巧,需要的朋友可以参考下
    2015-03-03
  • Golang详细讲解常用Http库及Gin框架的应用

    Golang详细讲解常用Http库及Gin框架的应用

    下面这篇文章主要给大家介绍了关于Golang常用的Http库及Gin框架,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2022-06-06
  • 解决vscode中golang插件依赖安装失败问题

    解决vscode中golang插件依赖安装失败问题

    这篇文章主要介绍了解决vscode中golang插件依赖安装失败问题,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-08-08
  • Go语言操作Excel的实现示例

    Go语言操作Excel的实现示例

    excelize是一个功能丰富且易于使用的Go语言库,它极大地简化了Excel文件的读写操作,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-12-12
  • 如何使用Goland IDE go mod 方式构建项目

    如何使用Goland IDE go mod 方式构建项目

    这篇文章主要介绍了如何使用Goland IDE go mod 方式构建项目,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-10-10
  • Go语言基础知识总结(语法、变量、数值类型、表达式、控制结构等)

    Go语言基础知识总结(语法、变量、数值类型、表达式、控制结构等)

    这篇文章主要介绍了Go语言基础知识总结(语法、变量、数值类型、表达式、控制结构等),本文汇总了Go语言的入门知识,需要的朋友可以参考下
    2014-10-10
  • Go设计模式之单例模式图文详解

    Go设计模式之单例模式图文详解

    单例模式是一种创建型设计模式,让你能够保证一个类只有一个实例,并提供一个访问该实例的全局节点,本文就通过图文给大家介绍一下Go的单例模式,需要的朋友可以参考下
    2023-07-07

最新评论