校园春色亚洲色图_亚洲视频分类_中文字幕精品一区二区精品_麻豆一区区三区四区产品精品蜜桃

主頁 > 知識庫 > 基于gin的golang web開發之認證利器jwt

基于gin的golang web開發之認證利器jwt

熱門標簽:赤峰電銷 利用地圖標注位置 貴州電話智能外呼系統 地圖區域圖標注后導出 杭州人工智能電銷機器人費用 谷歌美發店地圖標注 官渡電銷外呼管理系統怎么收費 江蘇呼叫中心外呼系統有效果嗎 400開頭電話怎樣申請

JSON Web Token(JWT)是一種很流行的跨域認證解決方案,JWT基于JSON可以在進行驗證的同時附帶身份信息,對于前后端分離項目很有幫助。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

JWT由三部分組成,每個部分之間用點.隔開,分別稱為HEADER、PAYLOAD和VERIFY SIGNATURE。HEADER和PAYLOAD經過base64解碼后為JSON明文。

  1. HEADER包含兩個字段,alg指明JWT的簽名算法,typ固定為JWT
  2. PAYLOAD中包含JWT的聲明信息,標準中定義了isssubaud等聲明字段,如果標準聲明不夠用的話,我們還可以增加自定義聲明。要注意兩點,第一PAYLOAD只是經過base64編碼,幾乎就等于是明文,不要包含敏感信息。第二不要在PAYLOAD中放入過多的信息,因為驗證通過以后每一個請求都要包含JWT,信息太多的話會造成一些沒有必要的資源浪費。
  3. VERIFY SIGNATURE為使用HEADER中指定的算法生成的簽名。例如alg:HS256簽名算法

HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload),密鑰)

了解完JWT的基本原理之后,我們來看一下在gin中是怎么使用JWT的。

引入gin-jwt中間件

在Gin中使用jwt有個開源項目gin-jwt,這項目幾乎包含了我們要用到的一切。例如定義PAYLOAD中的聲明、授權驗證的方法、是否使用COOKIE等等。下面來看一下官網給出的例子。

package main

import (
	"log"
	"net/http"
	"os"
	"time"

	jwt "github.com/appleboy/gin-jwt/v2"
	"github.com/gin-gonic/gin"
)

type login struct {
	Username string `form:"username" json:"username" binding:"required"`
	Password string `form:"password" json:"password" binding:"required"`
}

var identityKey = "id"

func helloHandler(c *gin.Context) {
	claims := jwt.ExtractClaims(c)
	user, _ := c.Get(identityKey)
	c.JSON(200, gin.H{
		"userID":  claims[identityKey],
		"userName": user.(*User).UserName,
		"text":   "Hello World.",
	})
}

type User struct {
	UserName string
	FirstName string
	LastName string
}

func main() {
	port := os.Getenv("PORT")
	r := gin.New()
	r.Use(gin.Logger())
	r.Use(gin.Recovery())

	if port == "" {
		port = "8000"
	}

	authMiddleware, err := jwt.New(jwt.GinJWTMiddleware{
		Realm:    "test zone",
		Key:     []byte("secret key"),
		Timeout:   time.Hour,
		MaxRefresh: time.Hour,
		IdentityKey: identityKey,
		PayloadFunc: func(data interface{}) jwt.MapClaims {
			if v, ok := data.(*User); ok {
				return jwt.MapClaims{
					identityKey: v.UserName,
				}
			}
			return jwt.MapClaims{}
		},
		IdentityHandler: func(c *gin.Context) interface{} {
			claims := jwt.ExtractClaims(c)
			return User{
				UserName: claims[identityKey].(string),
			}
		},
		Authenticator: func(c *gin.Context) (interface{}, error) {
			var loginVals login
			if err := c.ShouldBind(loginVals); err != nil {
				return "", jwt.ErrMissingLoginValues
			}
			userID := loginVals.Username
			password := loginVals.Password

			if (userID == "admin"  password == "admin") || (userID == "test"  password == "test") {
				return User{
					UserName: userID,
					LastName: "Bo-Yi",
					FirstName: "Wu",
				}, nil
			}

			return nil, jwt.ErrFailedAuthentication
		},
		Authorizator: func(data interface{}, c *gin.Context) bool {
			if v, ok := data.(*User); ok  v.UserName == "admin" {
				return true
			}

			return false
		},
		Unauthorized: func(c *gin.Context, code int, message string) {
			c.JSON(code, gin.H{
				"code":  code,
				"message": message,
			})
		},

		TokenLookup: "header: Authorization, query: token, cookie: jwt",
		TokenHeadName: "Bearer",
		TimeFunc: time.Now,
	})

	if err != nil {
		log.Fatal("JWT Error:" + err.Error())
	}

	errInit := authMiddleware.MiddlewareInit()

	if errInit != nil {
		log.Fatal("authMiddleware.MiddlewareInit() Error:" + errInit.Error())
	}

	r.POST("/login", authMiddleware.LoginHandler)

	r.NoRoute(authMiddleware.MiddlewareFunc(), func(c *gin.Context) {
		claims := jwt.ExtractClaims(c)
		log.Printf("NoRoute claims: %#v\n", claims)
		c.JSON(404, gin.H{"code": "PAGE_NOT_FOUND", "message": "Page not found"})
	})

	auth := r.Group("/auth")
	auth.GET("/refresh_token", authMiddleware.RefreshHandler)
	auth.Use(authMiddleware.MiddlewareFunc())
	{
		auth.GET("/hello", helloHandler)
	}

	if err := http.ListenAndServe(":"+port, r); err != nil {
		log.Fatal(err)
	}
}

我們可以看到jwt.GinJWTMiddleware用于聲明一個中間件。PayloadFunc方法中給默認的PAYLOAD增加了id字段,取值為UserName。Authenticator認證器,我們可以在這里驗證用戶身份,參數為*gin.Context,所以在這里我們可以像寫Gin Handler那樣獲取到Http請求中的各種內容。Authorizator授權器可以判斷判斷當前JWT是否有權限繼續訪問。當然還可以設置像過期時間,密鑰,是否設置COOKIE等其他選項。

登錄Handler

以上例子中配置了路由r.POST("/login", authMiddleware.LoginHandler)下面我們來看一下登錄過程是怎樣的。

func (mw *GinJWTMiddleware) LoginHandler(c *gin.Context) {
	if mw.Authenticator == nil {
		mw.unauthorized(c, http.StatusInternalServerError, mw.HTTPStatusMessageFunc(ErrMissingAuthenticatorFunc, c))
		return
	}

	data, err := mw.Authenticator(c)

	if err != nil {
		mw.unauthorized(c, http.StatusUnauthorized, mw.HTTPStatusMessageFunc(err, c))
		return
	}

	// Create the token
	token := jwt.New(jwt.GetSigningMethod(mw.SigningAlgorithm))
	claims := token.Claims.(jwt.MapClaims)

	if mw.PayloadFunc != nil {
		for key, value := range mw.PayloadFunc(data) {
			claims[key] = value
		}
	}

	expire := mw.TimeFunc().Add(mw.Timeout)
	claims["exp"] = expire.Unix()
	claims["orig_iat"] = mw.TimeFunc().Unix()
	tokenString, err := mw.signedString(token)

	if err != nil {
		mw.unauthorized(c, http.StatusUnauthorized, mw.HTTPStatusMessageFunc(ErrFailedTokenCreation, c))
		return
	}

	// set cookie
	if mw.SendCookie {
		expireCookie := mw.TimeFunc().Add(mw.CookieMaxAge)
		maxage := int(expireCookie.Unix() - mw.TimeFunc().Unix())

		if mw.CookieSameSite != 0 {
			c.SetSameSite(mw.CookieSameSite)
		}

		c.SetCookie(
			mw.CookieName,
			tokenString,
			maxage,
			"/",
			mw.CookieDomain,
			mw.SecureCookie,
			mw.CookieHTTPOnly,
		)
	}

	mw.LoginResponse(c, http.StatusOK, tokenString, expire)
}

LoginHandler整體邏輯還是比較簡單的,檢查并調用前面設置的Authenticator方法,驗證成功的話生成一個新的JWT,調用PayloadFunc方法設置PAYLOAD的自定義字段,根據SendCookie判斷是否需要在HTTP中設置COOKIE,最后調用LoginResponse方法設置返回值。

使用中間件

jwt-gin包提供了一個標準的Gin中間件,我們可以在需要驗證JWT的路由上設置中間件。前面例子中對路由組/auth增加了JWT驗證auth.Use(authMiddleware.MiddlewareFunc())

func (mw *GinJWTMiddleware) MiddlewareFunc() gin.HandlerFunc {
	return func(c *gin.Context) {
		mw.middlewareImpl(c)
	}
}

func (mw *GinJWTMiddleware) middlewareImpl(c *gin.Context) {
	claims, err := mw.GetClaimsFromJWT(c)
	if err != nil {
		mw.unauthorized(c, http.StatusUnauthorized, mw.HTTPStatusMessageFunc(err, c))
		return
	}

	if claims["exp"] == nil {
		mw.unauthorized(c, http.StatusBadRequest, mw.HTTPStatusMessageFunc(ErrMissingExpField, c))
		return
	}

	if _, ok := claims["exp"].(float64); !ok {
		mw.unauthorized(c, http.StatusBadRequest, mw.HTTPStatusMessageFunc(ErrWrongFormatOfExp, c))
		return
	}

	if int64(claims["exp"].(float64))  mw.TimeFunc().Unix() {
		mw.unauthorized(c, http.StatusUnauthorized, mw.HTTPStatusMessageFunc(ErrExpiredToken, c))
		return
	}

	c.Set("JWT_PAYLOAD", claims)
	identity := mw.IdentityHandler(c)

	if identity != nil {
		c.Set(mw.IdentityKey, identity)
	}

	if !mw.Authorizator(identity, c) {
		mw.unauthorized(c, http.StatusForbidden, mw.HTTPStatusMessageFunc(ErrForbidden, c))
		return
	}

	c.Next()
}

GetClaimsFromJWT方法在當前上下文中獲取JWT,失敗的話返回未授權。接著會判斷JWT是否過期,最后前面設置的Authorizator方法驗證是否有權限繼續訪問。

到此這篇關于基于gin的golang web開發之認證利器jwt的文章就介紹到這了,更多相關gin的golang web開發內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:
  • Gin golang web開發模型綁定實現過程解析
  • 基于gin的golang web開發:路由示例詳解
  • golang websocket 服務端的實現
  • Golang實現web文件共享服務的示例代碼
  • golang搭建靜態web服務器的實現方法
  • golang基于websocket實現的簡易聊天室程序

標簽:松原 泰安 黔西 鷹潭 武漢 保定 宜春 河池

巨人網絡通訊聲明:本文標題《基于gin的golang web開發之認證利器jwt》,本文關鍵詞  基于,gin,的,golang,web,開,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《基于gin的golang web開發之認證利器jwt》相關的同類信息!
  • 本頁收集關于基于gin的golang web開發之認證利器jwt的相關信息資訊供網民參考!
  • 推薦文章
    校园春色亚洲色图_亚洲视频分类_中文字幕精品一区二区精品_麻豆一区区三区四区产品精品蜜桃
    国产精品第13页| 国产在线乱码一区二区三区| 蜜桃一区二区三区四区| 99久久综合狠狠综合久久| 日韩精品在线一区二区| 一区二区三区日韩欧美| 国产精品66部| 欧美一区国产二区| 一区二区三区日韩欧美精品| eeuss影院一区二区三区| 欧美va亚洲va国产综合| 亚洲一区二区三区视频在线播放| 东方aⅴ免费观看久久av| 日韩三级伦理片妻子的秘密按摩| 亚洲视频1区2区| 成人在线一区二区三区| 精品剧情在线观看| 视频一区二区不卡| 在线观看av一区二区| 亚洲男人天堂av| 成人国产精品免费网站| 久久久天堂av| 国产一区在线观看视频| 精品毛片乱码1区2区3区| 日本三级韩国三级欧美三级| 欧美精品日韩综合在线| 亚洲人成精品久久久久久| 成人亚洲精品久久久久软件| 亚洲精品一区二区三区在线观看| 一区二区三区色| 欧美色图免费看| 亚洲人成网站在线| 日本丶国产丶欧美色综合| 国产欧美日本一区二区三区| 国产精品影视在线| 日韩天堂在线观看| 国产一区视频网站| 久久久久久久综合色一本| 国产在线一区二区综合免费视频| 欧美二区在线观看| 亚洲国产日韩一区二区| 精品婷婷伊人一区三区三| 国产日产欧产精品推荐色 | 日韩视频免费直播| 紧缚奴在线一区二区三区| 69堂国产成人免费视频| 秋霞电影网一区二区| 欧美一区二区视频免费观看| 亚洲美女精品一区| 91视频精品在这里| 99麻豆久久久国产精品免费 | 亚洲精品亚洲人成人网在线播放| bt7086福利一区国产| 国产亚洲成av人在线观看导航| 国产成人精品网址| 国产精品日日摸夜夜摸av| 色视频成人在线观看免| 亚洲免费观看高清| 91麻豆精品久久久久蜜臀| 日韩国产精品大片| 国产午夜亚洲精品理论片色戒| 92精品国产成人观看免费 | 欧美色图一区二区三区| 亚洲高清免费一级二级三级| 91亚洲精品久久久蜜桃网站| 国产无一区二区| 欧美图区在线视频| 亚洲va国产va欧美va观看| 久久视频一区二区| 国产91在线|亚洲| 亚洲午夜影视影院在线观看| 精品久久久久久综合日本欧美| 国产成人高清在线| 亚洲精品免费在线观看| 久久综合九色综合97婷婷女人 | 亚洲男人都懂的| 欧美r级在线观看| 不卡的av在线播放| 性欧美疯狂xxxxbbbb| 欧美不卡一区二区三区四区| 91论坛在线播放| 久久国产人妖系列| 亚洲国产精品久久久久婷婷884| 欧美α欧美αv大片| 欧美午夜精品一区| 久久99精品国产| 亚洲综合视频在线| 久久精品人人做| 欧美精品第一页| 99re热视频这里只精品| 国产激情一区二区三区四区| 亚洲综合精品久久| 亚洲人成亚洲人成在线观看图片 | 欧美一区二区三区四区高清| www.欧美色图| 激情久久久久久久久久久久久久久久| 夜夜嗨av一区二区三区| 久久一区二区视频| 91日韩一区二区三区| 国产精品综合二区| 亚洲电影一区二区| 亚洲欧美日韩一区| 国产日产欧美一区| 久久久久九九视频| 3751色影院一区二区三区| 欧美性猛交xxxx乱大交退制版| 狠狠色丁香婷综合久久| 蜜臀av一区二区| 亚洲伊人色欲综合网| 亚洲黄色在线视频| 自拍偷拍国产精品| 国产精品久久福利| 久久免费午夜影院| 久久久久久久久久久久电影| 欧美一区二区精美| 日韩一级二级三级| 欧美福利一区二区| 91.麻豆视频| 欧美人妇做爰xxxⅹ性高电影| 欧美色综合网站| 色综合激情五月| 精品婷婷伊人一区三区三| 一本一道久久a久久精品| 色欧美乱欧美15图片| 97久久精品人人澡人人爽| 色婷婷久久综合| 9色porny自拍视频一区二区| 91在线视频观看| 91成人在线观看喷潮| 欧美三级在线看| 欧美伦理电影网| 日韩欧美色综合网站| 欧美成人三级在线| 国产精品毛片久久久久久久| 国产亚洲欧美一级| 亚洲三级在线免费| 亚洲欧美偷拍三级| 全国精品久久少妇| 久久国产精品区| 国产成人在线免费观看| 一本久久a久久精品亚洲| 色999日韩国产欧美一区二区| 91精品久久久久久久99蜜桃| 欧美一级日韩不卡播放免费| 国产亚洲美州欧州综合国| 国产视频视频一区| 亚洲午夜影视影院在线观看| 日本不卡视频在线观看| 成人美女视频在线看| 色综合中文综合网| 国产精品高潮久久久久无| 亚洲精品日产精品乱码不卡| 日韩电影免费在线观看网站| 国产综合久久久久久久久久久久| 成人aa视频在线观看| 欧美日韩在线电影| 国产日韩欧美麻豆| 一区二区三区电影在线播| 免费欧美在线视频| 91免费观看视频| 精品一二三四区| 欧美一区二区三区在线电影 | 免费成人美女在线观看.| 风间由美性色一区二区三区| 91看片淫黄大片一级在线观看| 在线观看91av| 中文字幕一区在线| 九色综合狠狠综合久久| 99精品偷自拍| 久久久噜噜噜久久人人看 | 一区二区免费视频| 久久av老司机精品网站导航| 国产·精品毛片| 欧美成人精精品一区二区频| 中文字幕第一区二区| 蜜桃视频一区二区| 97久久人人超碰| 久久精品日产第一区二区三区高清版 | 毛片不卡一区二区| 91福利社在线观看| 国产调教视频一区| 精品中文字幕一区二区小辣椒| 欧美在线一区二区| **网站欧美大片在线观看| 久久精品国产精品亚洲精品| 欧美亚洲一区二区在线| 国产欧美在线观看一区| 黄页网站大全一区二区| 欧美午夜精品一区二区蜜桃| 一区二区三区在线不卡| 国产白丝精品91爽爽久久| 久久色成人在线| 一区二区三区国产精华| 91原创在线视频| 精品人在线二区三区| 日韩不卡一区二区三区| 欧美高清精品3d| 亚洲v精品v日韩v欧美v专区| 欧美三区在线视频| 亚洲综合成人在线视频|