作者:@daemon365
本文为作者原创,转载请注明出处:https://www.cnblogs.com/daemon365/p/15162758.html
什么是JWT?
JWT全称JSON Web Token是一种跨域认证解决方案,属于一个开放的标准,它规定了一种Token实现方式,目前多用于前后端分离项目和OAuth2.0业务场景下。
JWT作用?
JWT就是一种基于Token的轻量级认证模式,服务端认证通过后,会生成一个JSON对象,经过签名后得到一个Token(令牌)再发回给用户,用户后续请求只需要带上这个Token,服务端解密之后就能获取该用户的相关信息了。
下载jwt
| go get -u github.com/golang-jwt/jwt |
生成JWT和解析JWT
我们在这里直接使用jwt-go这个库来实现我们生成JWT和解析JWT的功能。
定义需求
我们需要定制自己的需求来决定JWT中保存哪些数据
| type MyClaims struct { |
| UserID uint64 `json:"user_id"` |
| Username string `json:"username"` |
| jwt.StandardClaims |
| } |
定义JWT的过期时间和Secret(盐):
| const TokenExpireDuration = time.Hour * 24 * 2 |
| var Secret = []byte("i am zhaohaiyu") |
生成JWT
| |
| func genToken(userID uint64, username string) (string, error) { |
| var claims = MyClaims{ |
| userID, |
| username, |
| jwt.StandardClaims{ |
| ExpiresAt: time.Now().Add(TokenExpireDuration).Unix(), |
| Issuer: "zhaohaiyu", |
| }, |
| } |
| token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) |
| signedToken, err := token.SignedString([]byte(Secret)) |
| if err != nil { |
| return "", fmt.Errorf("生成token失败:%v", err) |
| } |
| return signedToken, nil |
| } |
解析JWT
| |
| func ParseToken(tokenStr string) (*MyClaims, error) { |
| token, err := jwt.ParseWithClaims(tokenStr, &MyClaims{}, func(token *jwt.Token) (i interface{}, err error) { |
| return Secret, nil |
| }) |
| if err != nil { |
| return nil, err |
| } |
| if claims, ok := token.Claims.(*MyClaims); ok && token.Valid { |
| return claims, nil |
| } |
| return nil, errors.New("invalid token") |
| } |
在gin框架中使用JWT
| r.POST("/auth/token", GetTokenHandler) |
登录生成token
| func GetTokenHandler(c *gin.Context) { |
| |
| var user UserInfo |
| err := c.ShouldBind(&user) |
| if err != nil { |
| c.JSON(http.StatusOK, gin.H{ |
| "code": 1001, |
| "err_info": "参数错误", |
| }) |
| return |
| } |
| |
| if user.Username == "root" && user.Password == "123" { |
| |
| tokenString, err := GenToken(user.Username) |
| if err != nil { |
| c.JSON(http.StatusOK, gin.H{ |
| "code": 1001, |
| "err_info": "生成token错误", |
| }) |
| return |
| } |
| c.JSON(http.StatusOK, gin.H{ |
| "code": 2000, |
| "msg": "success", |
| "data": gin.H{"token": tokenString}, |
| }) |
| return |
| } else { |
| c.JSON(http.StatusOK, gin.H{ |
| "code": 2002, |
| "msg": "用户名或密码错误", |
| }) |
| return |
| } |
| return |
| } |
jwt中间件验证
| |
| func JWThMiddleware() func(c *gin.Context) { |
| return func(c *gin.Context) { |
| |
| |
| token := c.Request.Header.Get("token") |
| if token == "" { |
| |
| c.Abort() |
| return |
| } |
| |
| mc, err := ParseToken(token) |
| if err != nil { |
| |
| c.Abort() |
| return |
| } |
| |
| c.Set("userID", mc.UserID) |
| c.Next() |
| } |
| } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?