• 设为首页
  • 收藏本站
  • 积分充值
  • VIP赞助
  • 手机版
  • 微博
  • 微信
    微信公众号 添加方式:
    1:搜索微信号(888888
    2:扫描左侧二维码
  • 快捷导航
    福建二哥 门户 查看主题

    一文详解如何在Golang中实现JWT认证与授权

    发布者: 琛瑞6678 | 发布时间: 2025-8-14 09:10| 查看数: 100| 评论数: 0|帖子模式

    在现代Web应用中,安全性是一个非常重要的课题。JWT(JSON Web Token)作为一种常用的认证与授权机制,已被广泛应用于各种系统中。它的优势在于轻量级、跨平台,并且非常适合分布式系统。在本文中,我们将通过Golang实现JWT认证与授权,帮助你构建更安全的API。

    什么是JWT?

    JWT(JSON Web Token)是一种开放标准(RFC 7519),用于在网络应用环境间以一个简短的字符串安全地传输信息。JWT通常用于用户认证和授权,它由三个部分组成:
    1.头部(Header):通常包含两部分信息,类型(JWT)和签名算法(如HMAC SHA256或RSA)。
    2.有效载荷(Payload):包含我们要传递的数据,通常是用户的身份信息或权限等。
    3.签名(Signature):确保消息的完整性和防止篡改。它是通过头部和有效载荷用私钥签名生成的。
    JWT的结构如下:
    1. header.payload.signature
    复制代码

    为什么选择JWT?

    无状态性:JWT是自包含的,因此不需要存储会话信息,适合分布式系统。
    跨平台:JWT的结构标准化,几乎所有语言都可以生成和解析JWT。
    灵活性:可以将任意信息存储在JWT中,如用户ID、权限、过期时间等。

    在Golang中实现JWT认证与授权


    1. 安装所需的库

    我们将使用github.com/dgrijalva/jwt-go库来生成和验证JWT。首先,使用go get安装该库:
    1. go get github.com/dgrijalva/jwt-go
    复制代码
    2. 创建JWT生成与解析功能

    我们将创建一个简单的JWT生成和验证模块,允许用户通过用户名和密码登录,并获取一个JWT进行后续请求。
    生成JWT
    在auth.go文件中,编写JWT生成函数:
    1. package main

    2. import (
    3.     "github.com/dgrijalva/jwt-go"
    4.     "time"
    5.     "log"
    6. )

    7. // 密钥用于签名和验证JWT
    8. var jwtKey = []byte("secret")

    9. // 用户信息结构体
    10. type Claims struct {
    11.     Username string `json:"username"`
    12.     jwt.StandardClaims
    13. }

    14. // 生成JWT
    15. func GenerateJWT(username string) (string, error) {
    16.     expirationTime := time.Now().Add(1 * time.Hour) // 设置JWT过期时间为1小时
    17.     claims := &Claims{
    18.         Username: username,
    19.         StandardClaims: jwt.StandardClaims{
    20.             ExpiresAt: expirationTime.Unix(),
    21.         },
    22.     }

    23.     // 创建一个新的JWT对象,使用HMAC SHA256算法签名
    24.     token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)

    25.     // 使用密钥签名并返回生成的JWT字符串
    26.     return token.SignedString(jwtKey)
    27. }
    复制代码
    解析JWT
    然后,编写JWT解析函数,验证其有效性并提取用户信息:
    1. // 解析JWT并返回用户名
    2. func ParseJWT(tokenStr string) (string, error) {
    3.     claims := &Claims{}
    4.     token, err := jwt.ParseWithClaims(tokenStr, claims, func(token *jwt.Token) (interface{}, error) {
    5.         // 返回签名时使用的密钥
    6.         return jwtKey, nil
    7.     })

    8.     if err != nil {
    9.         return "", err
    10.     }

    11.     if !token.Valid {
    12.         return "", err
    13.     }

    14.     return claims.Username, nil
    15. }
    复制代码
    3. 实现登录接口

    接下来,我们实现一个登录接口,用户可以通过提供用户名和密码来获取JWT。
    1. package main

    2. import (
    3.     "github.com/gin-gonic/gin"
    4.     "net/http"
    5. )

    6. // 假设的用户数据,实际应用中应使用数据库
    7. var users = map[string]string{
    8.     "user1": "password1",
    9.     "user2": "password2",
    10. }

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

    13.     // 登录接口
    14.     r.POST("/login", func(c *gin.Context) {
    15.         var loginData map[string]string
    16.         if err := c.ShouldBindJSON(&loginData); err != nil {
    17.             c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid input"})
    18.             return
    19.         }

    20.         username, password := loginData["username"], loginData["password"]

    21.         // 验证用户名和密码
    22.         if correctPassword, exists := users[username]; exists && correctPassword == password {
    23.             // 生成JWT
    24.             token, err := GenerateJWT(username)
    25.             if err != nil {
    26.                 c.JSON(http.StatusInternalServerError, gin.H{"error": "Could not generate token"})
    27.                 return
    28.             }

    29.             c.JSON(http.StatusOK, gin.H{"token": token})
    30.         } else {
    31.             c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid username or password"})
    32.         }
    33.     })

    34.     r.Run(":8080")
    35. }
    复制代码
    4. 实现受保护的路由

    为了保护需要授权的路由,我们需要编写中间件来验证JWT。只有通过验证的请求才能访问这些路由。
    1. // JWT验证中间件
    2. func JWTMiddleware() gin.HandlerFunc {
    3.     return func(c *gin.Context) {
    4.         // 获取Authorization头部
    5.         tokenStr := c.GetHeader("Authorization")
    6.         if tokenStr == "" {
    7.             c.JSON(http.StatusUnauthorized, gin.H{"error": "Missing token"})
    8.             c.Abort()
    9.             return
    10.         }

    11.         // 解析JWT并获取用户名
    12.         username, err := ParseJWT(tokenStr)
    13.         if err != nil {
    14.             c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid token"})
    15.             c.Abort()
    16.             return
    17.         }

    18.         // 将用户名添加到上下文中,以便后续使用
    19.         c.Set("username", username)
    20.         c.Next()
    21.     }
    22. }

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

    25.     // 登录接口
    26.     r.POST("/login", func(c *gin.Context) {
    27.         var loginData map[string]string
    28.         if err := c.ShouldBindJSON(&loginData); err != nil {
    29.             c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid input"})
    30.             return
    31.         }

    32.         username, password := loginData["username"], loginData["password"]

    33.         if correctPassword, exists := users[username]; exists && correctPassword == password {
    34.             token, err := GenerateJWT(username)
    35.             if err != nil {
    36.                 c.JSON(http.StatusInternalServerError, gin.H{"error": "Could not generate token"})
    37.                 return
    38.             }

    39.             c.JSON(http.StatusOK, gin.H{"token": token})
    40.         } else {
    41.             c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid username or password"})
    42.         }
    43.     })

    44.     // 受保护的路由,必须通过JWT验证
    45.     authorized := r.Group("/protected")
    46.     authorized.Use(JWTMiddleware())
    47.     authorized.GET("/hello", func(c *gin.Context) {
    48.         username := c.MustGet("username").(string)
    49.         c.JSON(http.StatusOK, gin.H{
    50.             "message": "Hello, " + username,
    51.         })
    52.     })

    53.     r.Run(":8080")
    54. }
    复制代码
    5. 测试JWT认证

    ##16bWaaVUGAdS8d39CilS9PXEtEptU809NqHfKBuiVYk=##
    首先,通过/login接口获取JWT:
    1. curl -X POST http://localhost:8080/login -H "Content-Type: application/json" -d '{"username":"user1", "password":"password1"}'
    复制代码
    返回结果:
    1. { "token": "your-jwt-token" }
    复制代码
    然后,使用返回的JWT访问受保护的路由:
    1. curl -X GET http://localhost:8080/protected/hello -H "Authorization: your-jwt-token"
    复制代码
    返回结果:
    1. { "message": "Hello, user1" }
    复制代码
    结语

    通过本文的讲解,你应该已经掌握了如何在Golang中使用JWT进行认证与授权。JWT凭借其无状态性和跨平台的特点,成为了分布式系统中实现认证与授权的理想选择。你可以将这个基本的认证系统进一步扩展,如支持权限控制、刷新令牌等功能。
    以上就是一文详解如何在Golang中实现JWT认证与授权的详细内容,更多关于Golang JWT认证与授权的资料请关注脚本之家其它相关文章!

    来源:互联网
    免责声明:如果侵犯了您的权益,请联系站长(1277306191@qq.com),我们会及时删除侵权内容,谢谢合作!

    最新评论

    QQ Archiver 手机版 小黑屋 福建二哥 ( 闽ICP备2022004717号|闽公网安备35052402000345号 )

    Powered by Discuz! X3.5 © 2001-2023

    快速回复 返回顶部 返回列表