文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

前后端分离必备, Golang Gin中如何使用JWT(JsonWebToken)中间件?

2024-12-03 15:20

关注

 什么是JWT?

JSON Web Token(缩写 JWT)是目前最流行的跨域认证解决方案,也是目前前后端分离项目中普遍使用的认证技术. 本文介绍如何在Golang Gin Web框架中使用JWT认证中间件以及模拟测试, 以供参考, 关于JWT详细原理可以参考:

主要流程

流程图


该流程图描述了服务端代码中的Token构造, 以及认证流程.

服务端代码

main.go中填充以下代码, 运行go run main.go, 开启Web服务.

  1. package main 
  2.  
  3. import ( 
  4.   jwt_lib "github.com/dgrijalva/jwt-go" 
  5.   "github.com/dgrijalva/jwt-go/request" 
  6.   "github.com/gin-gonic/gin" 
  7.   "log" 
  8.   "time" 
  9.  
  10. var ( 
  11.   mysupersecretpassword = "unicornsAreAwesome" 
  12.  
  13. func Auth(secret string) gin.HandlerFunc { 
  14.   return func(c *gin.Context) { 
  15.     //log.Printf("Request:\n%+v", c.Request) 
  16.     // ParseFromRequest方法提取路径请求中的JWT令牌, 并进行验证 
  17.     token, err := request.ParseFromRequest(c.Request, request.OAuth2Extractor, func(token *jwt_lib.Token) (interface{}, error) { 
  18.       b := ([]byte(secret)) 
  19.       //log.Printf("b:%+v", b) 
  20.       return b, nil 
  21.     }) 
  22.  
  23.     log.Printf("token:%+v", token) 
  24.     if err != nil { 
  25.       c.AbortWithError(401, err) 
  26.     } 
  27.   } 
  28.  
  29. func main() { 
  30.   r := gin.Default() 
  31.  
  32.   public := r.Group("/api"
  33.  
  34.   // 定义根路由, 访问http://locahost:8080/api/可以获取到token 
  35.   public.GET("/", func(c *gin.Context) { 
  36.     // Create the token New方法接受一个签名方法的接口类型(SigningMethod)参数, 返回一个Token结构指针 
  37.     // GetSigningMethod(签名算法algorithm) 
  38.     token := jwt_lib.New(jwt_lib.GetSigningMethod("HS256")) //默认是签名算法是HMAC SHA256(写成 HS256) 
  39.     log.Printf("token:%+v", token) 
  40.     //2020/12/10 22:32:02 token:&{Raw: Method:0xc00000e2a0 Header:map[alg:HS256 typ:JWT] Claims:map[] Signature: Valid:false
  41.  
  42.     // Set some claims 设置Id和过期时间字段, MapClaims实现了Clainms接口 
  43.     token.Claims = jwt_lib.MapClaims{ 
  44.       "Id":  "Christopher"
  45.       "exp"time.Now().Add(time.Hour * 1).Unix(), 
  46.     } 
  47.     // Sign and get the complete encoded token as a string // 签名并得到完整编码后的Token字符串 
  48.     tokenString, err := token.SignedString([]byte(mysupersecretpassword)) 
  49.     //{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJJZCI6IkNocmlzdG9waGVyIiwiZXhwIjoxNjA3NjE0MzIyfQ.eQd7ztDn3706GrpitgnikKgOtzx-RHnq7cr2eqUlsZo"
  50.     if err != nil { 
  51.       c.JSON(500, gin.H{"message""Could not generate token"}) 
  52.     } 
  53.     c.JSON(200, gin.H{"token": tokenString}) 
  54.   }) 
  55.  
  56.   // 定义需要Token验证通过才能访问的私有接口组http://localhost:8080/api/private 
  57.   private := r.Group("/api/private"
  58.   private.Use(Auth(mysupersecretpassword)) // 使用JWT认证中间件(带参数) 
  59.  
  60.    
  61.  
  62.   // 定义具体的私有根接口:http://localhost:8080/api/private/ 
  63.   private.GET("/", func(c *gin.Context) { 
  64.     c.JSON(200, gin.H{"message""Hello from private"}) 
  65.   }) 
  66.  
  67.   r.Run("localhost:8080"

客户端代码

新建jwt_test.go文件, 填充以下代码, 运行go test执行单元测试.

  1. package test_test 
  2.  
  3. import ( 
  4.   "encoding/json" 
  5.   . "github.com/smartystreets/goconvey/convey" //https://github.com/smartystreets/goconvey GoConvey是Golang的测试框架,集成go test, 支持终端和浏览器模式. 
  6.   "io/ioutil" 
  7.   "log" 
  8.   "net/http" 
  9.   "strings" 
  10.   "testing" 
  11.  
  12. type User struct { 
  13.   Username string `json:"username"
  14.   Password string `json:"password"
  15.  
  16. type Response struct { 
  17.   Token string `json:"token"
  18.  
  19. func createNewsUser(username, password string) *User { 
  20.   return &User{username, password
  21.  
  22. func TestLogin(t *testing.T) { 
  23.   Convey("Should be able to login", t, func() { 
  24.     user := createNewsUser("jonas""1234"
  25.     jsondata, _ := json.Marshal(user
  26.     userData := strings.NewReader(string(jsondata)) 
  27.     log.Printf("userData:%+v", userData) 
  28.     // 这里模拟用户登录, 实际上后台没有使用用户名和密码, 该接口直接返回内部生成的Token 
  29.     req, _ := http.NewRequest("GET""http://localhost:8080/api/", userData) 
  30.     req.Header.Set("Content-Type""application/json"
  31.     client := &http.Client{} 
  32.     res, _ := client.Do(req) 
  33.     //log.Printf("res:%+v", res) 
  34.     So(res.StatusCode, ShouldEqual, 200) //对响应码进行断言, 期望得到状态码为200 
  35.  
  36.     Convey("Should be able to parse body", func() { //解析响应体 
  37.       body, err := ioutil.ReadAll(res.Body) 
  38.       defer res.Body.Close() 
  39.       So(err, ShouldBeNil) 
  40.       Convey("Should be able to get json back", func() { 
  41.         responseData := new(Response) 
  42.         err := json.Unmarshal(body, responseData) 
  43.         So(err, ShouldBeNil) 
  44.         log.Printf("responseData:%s", responseData) 
  45.         Convey("Should be able to be authorized", func() { 
  46.           token := responseData.Token //提取Token 
  47.           log.Printf("token:%s", token) 
  48.           // 构造带Token的请求 
  49.           req, _ := http.NewRequest("GET""http://localhost:8080/api/private", nil) 
  50.           req.Header.Set("Authorization""Bearer "+token) //设置认证头 
  51.           client = &http.Client{} 
  52.           res, _ := client.Do(req) 
  53.           body, err := ioutil.ReadAll(res.Body) 
  54.           if err != nil { 
  55.             log.Printf("Read body failed, %s", err.Error()) 
  56.           } 
  57.           log.Printf("Body:%s", string(body)) 
  58.           So(res.StatusCode, ShouldEqual, 200) 
  59.         }) 
  60.       }) 
  61.     }) 
  62.   }) 

参考文档

gin-gonic/contrib/jwt中间件: https://github.com/gin-gonic/contrib/tree/master/jwt

 

来源:云原生云内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯