自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

前后端分離必備, Golang Gin中如何使用JWT(JsonWebToken)中間件?

開發(fā) 前端
JSON Web Token(縮寫 JWT)是目前最流行的跨域認證解決方案,也是目前前后端分離項目中普遍使用的認證技術(shù). 本文介紹如何在Golang Gin Web框架中使用JWT認證中間件以及模擬測試.

[[357411]]

 什么是JWT?

JSON Web Token(縮寫 JWT)是目前最流行的跨域認證解決方案,也是目前前后端分離項目中普遍使用的認證技術(shù). 本文介紹如何在Golang Gin Web框架中使用JWT認證中間件以及模擬測試, 以供參考, 關(guān)于JWT詳細原理可以參考:

  • JWT RFC: https://tools.ietf.org/html/rfc7519
  • JWT IETF: http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html
  • JSON Web Token入門教程: http://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html

主要流程

  • 初始化Gin引擎
  • 定義獲取Token的接口, 訪問該接口, 內(nèi)部自動生成JWT令牌, 并返回給前端
  • 定義需要認證的路由接口, 使用JWT中間件進行認證, 中間件由
  • 利用GoConvey(Golang的測試框架,集成go test, 支持終端和瀏覽器模式), 構(gòu)造客戶端, 填寫Token, 模擬前端訪問
  • JWT中間件進行認證, 認證通過則返回消息體, 否則直接返回401或其他錯誤

流程圖


該流程圖描述了服務(wù)端代碼中的Token構(gòu)造, 以及認證流程.

服務(wù)端代碼

main.go中填充以下代碼, 運行g(shù)o run main.go, 開啟Web服務(wù).

  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)參數(shù), 返回一個Token結(jié)構(gòu)指針 
  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 設(shè)置Id和過期時間字段, MapClaims實現(xiàn)了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認證中間件(帶參數(shù)) 
  59.  
  60.   /* 
  61.     Set this header in your request to get here. 
  62.     Authorization: Bearer `token` 
  63.   */ 
  64.  
  65.   // 定義具體的私有根接口:http://localhost:8080/api/private/ 
  66.   private.GET("/", func(c *gin.Context) { 
  67.     c.JSON(200, gin.H{"message""Hello from private"}) 
  68.   }) 
  69.  
  70.   r.Run("localhost:8080"

客戶端代碼

新建jwt_test.go文件, 填充以下代碼, 運行g(shù)o test執(zhí)行單元測試.

  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.     // 這里模擬用戶登錄, 實際上后臺沒有使用用戶名和密碼, 該接口直接返回內(nèi)部生成的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) //對響應(yīng)碼進行斷言, 期望得到狀態(tài)碼為200 
  35.  
  36.     Convey("Should be able to parse body", func() { //解析響應(yīng)體 
  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.           // 構(gòu)造帶Token的請求 
  49.           req, _ := http.NewRequest("GET""http://localhost:8080/api/private", nil) 
  50.           req.Header.Set("Authorization""Bearer "+token) //設(shè)置認證頭 
  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

 

責任編輯:姜華 來源: 云原生云
相關(guān)推薦

2024-12-09 00:00:15

Gin框架中間件

2024-07-29 00:01:00

2024-01-05 08:17:53

FiberGolang路由

2019-07-09 05:44:35

前后端分離架構(gòu)接口規(guī)范

2022-04-06 07:50:57

JWT后端Spring

2024-02-06 14:05:00

Go中間件框架

2020-08-19 08:39:05

中間件前端設(shè)計模式

2019-06-12 19:00:14

前后端分離AppJava

2019-08-12 08:00:00

ASP.NetASP.Net Cor編程語言

2025-02-08 11:49:42

2021-02-11 08:21:02

中間件開發(fā)CRUD

2011-05-24 15:10:48

2023-02-08 16:29:58

前后端開發(fā)

2016-11-11 21:00:46

中間件

2021-06-15 10:01:02

應(yīng)用系統(tǒng)軟件

2023-09-21 10:44:41

Web服務(wù)Swagger前端

2023-12-06 07:14:28

前端API中間件

2018-07-29 12:27:30

云中間件云計算API

2018-02-01 10:19:22

中間件服務(wù)器系統(tǒng)

2022-11-18 07:54:02

Go中間件項目
點贊
收藏

51CTO技術(shù)棧公眾號