<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
JWT全稱JSON Web Token是一種跨域認證解決方案,屬於一個開放的標準,它規定了一種Token實現方式,目前多用於前後端分離專案和OAuth2.0業務場景下。
傳統的Cookie-Sesson模式佔用伺服器記憶體, 拓展性不好,遇到叢集或者跨服務驗證的場景的話, 要支援Sesson複製或者sesson持久化
在伺服器驗證之後, 得到使用者資訊JSON
{ "user_id": "xxxxxx", "role": "xxxxxx", "refresh_token": "xxxxx" }
JWT是一個很長的字串
eyJhbGciOiJI123afasrwrqqewrcCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
它由三部分組成, 每部分用點(.)分隔, 三個部分依次如下
Header是一個經過BASE64URL演演算法加密過的JSON物件, 解密後如下
{ "alg": "HS256", "typ": "JWT" }
其中, alg屬性表示簽名所用的演演算法,預設是HS256;
typ則表示當前token的型別, 而JWT的型別則為jwt
與BASE64類似, 由於+、/、=這幾個符號在URL中有特殊含義, 因此BASE64RUL演演算法, 把這幾個符號進行了替換
+ -> -
= -> 被忽略
/ -> _
Payload部分也是JSON物件經過BASE64URL演演算法轉成字串的, Payload部分包含7個基本欄位
也可以往裡面塞入自定義的業務欄位, 如下
user_id
role
Signature 部分是對前兩部分的簽名,防止資料篡改。
首先,需要指定一個金鑰(secret)。這個金鑰只有伺服器才知道,不能洩露給使用者。然後,使用 Header 裡面指定的簽名演演算法(預設是 HMAC SHA256),按照下面的公式產生簽名。
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
當系統接收到TOKEN時, 拿出Header和Payload的字串用.拼接在一起之後, 用Header裡面指定的雜湊方法通過公式
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
進行加密得出密文
然後用剛剛得出的密文與TOKEN傳過來的密文對比, 如果相等則表明密文沒有更改.
go get -u github.com/dgrijalva/jwt-go go get github.com/gin-gonic/gin
var Secret = []byte("whatasecret") // jwt過期時間, 按照實際環境設定 const expiration = 2 * time.Minute type Claims struct { // 自定義欄位, 可以存在使用者名稱, 使用者ID, 使用者角色等等 Username string // jwt.StandardClaims包含了官方定義的欄位 jwt.StandardClaims } func GenToken(username string) (string, error) { // 建立宣告 a := &Claims{ Username: username, StandardClaims: jwt.StandardClaims{ ExpiresAt: time.Now().Add(expiration).Unix(), // 過期時間 IssuedAt: time.Now().Unix(), // 簽發時間 Issuer: "gin-jwt-demo", // 簽發者 Id: "", // 按需求選這個, 有些實現中, 會控制這個ID是不是在黑/白名單來判斷是否還有效 NotBefore: 0, // 生效起始時間 Subject: "", // 主題 }, } // 用指定的雜湊方法建立簽名物件 tt := jwt.NewWithClaims(jwt.SigningMethodHS256, a) // 用上面的宣告和簽名物件簽名字串token // 1. 先對Header和PayLoad進行Base64URL轉換 // 2. Header和PayLoadBase64URL轉換後的字串用.拼接在一起 // 3. 用secret對拼接在一起之後的字串進行HASH加密 // 4. 連在一起返回 return tt.SignedString(Secret) } func ParseToken(tokenStr string) (*Claims, error) { // 第三個引數: 提供一個回撥函數用於提供要選擇的祕鑰, 回撥函數裡面的token引數,是已經解析但未驗證的,可以根據token裡面的值做一些邏輯, 如`kid`的判斷 token, err := jwt.ParseWithClaims(tokenStr, &Claims{}, func(token *jwt.Token) (interface{}, error) { return Secret, nil }) if err != nil { return nil, err } // 校驗token if claims, ok := token.Claims.(*Claims); ok && token.Valid { return claims, nil } return nil, errors.New("invalid token") }
type Claims struct { // 自定義欄位, 可以存在使用者名稱, 使用者ID, 使用者角色等等 Username string // jwt.StandardClaims包含了官方定義的欄位 jwt.StandardClaims } type StandardClaims struct { Audience string `json:"aud,omitempty"` ExpiresAt int64 `json:"exp,omitempty"` Id string `json:"jti,omitempty"` IssuedAt int64 `json:"iat,omitempty"` Issuer string `json:"iss,omitempty"` NotBefore int64 `json:"nbf,omitempty"` Subject string `json:"sub,omitempty"` }
GenToken方法為某個username生成一個token, 每次生成都不一樣
jwt.NewWithClaims(jwt.SigningMethodHS256, a)宣告了一個簽名物件, 並且指定了HS256的雜湊演演算法
token.SignedString(Secret)表明用剛剛的宣告物件和SECRET利用指定的雜湊演演算法去加密,包含下面流程
func GenToken(username string) (string, error) { // 建立宣告 a := &Claims{ Username: username, StandardClaims: jwt.StandardClaims{ ExpiresAt: time.Now().Add(expiration).Unix(), // 過期時間 IssuedAt: time.Now().Unix(), // 簽發時間 Issuer: "gin-jwt-demo", // 簽發者 Id: "", // 按需求選這個, 有些實現中, 會控制這個ID是不是在黑/白名單來判斷是否還有效 NotBefore: 0, // 生效起始時間 Subject: "", // 主題 }, } // 用指定的雜湊方法建立簽名物件 tt := jwt.NewWithClaims(jwt.SigningMethodHS256, a) // 用上面的宣告和簽名物件簽名字串token // 1. 先對Header和PayLoad進行Base64URL轉換 // 2. Header和PayLoadBase64URL轉換後的字串用.拼接在一起 // 3. 用secret對拼接在一起之後的字串進行HASH加密 // 4. 連在一起返回 return tt.SignedString(Secret) }
ParseToken方法解析一個Token, 並驗證Token是否生效
jwt.ParseWithClaims方法, 用於解析Token, 其第三個引數:
提供一個回撥函數用於提供要選擇的祕鑰, 回撥函數裡面的token引數,是已經解析但未驗證的,可以根據token裡面的值做一些邏輯, 如判斷kid來選用不同的secret
KID(可選): 代表祕鑰序號。開發人員可以用它標識認證token的某一祕鑰
func ParseToken(tokenStr string) (*Claims, error) { // 第三個引數: 提供一個回撥函數用於提供要選擇的祕鑰, 回撥函數裡面的token引數,是已經解析但未驗證的,可以根據token裡面的值做一些邏輯, 如`kid`的判斷 token, err := jwt.ParseWithClaims(tokenStr, &Claims{}, func(token *jwt.Token) (interface{}, error) { return Secret, nil }) if err != nil { return nil, err } // 校驗token if claims, ok := token.Claims.(*Claims); ok && token.Valid { return claims, nil } return nil, errors.New("invalid token") }
從Header中取出Authorization並拿去解析jwt.ParseToken,
驗證token是否被串改, 是否過期
從token取出有效資訊並設定到上下文
func JWTAuthMiddleware() func(ctx *gin.Context) { return func(ctx *gin.Context) { // 根據實際情況取TOKEN, 這裡從request header取 tokenStr := ctx.Request.Header.Get("Authorization") if tokenStr == "" { ctx.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{ "code": code.ERR_AUTH_NULL, "msg": code.GetMsg(code.ERR_AUTH_NULL), }) return } claims, err := jwt.ParseToken(tokenStr) if err != nil { ctx.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{ "code": code.ERR_AUTH_INVALID, "msg": code.GetMsg(code.ERR_AUTH_INVALID), }) return } else if time.Now().Unix() > claims.ExpiresAt { ctx.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{ "code": code.ERR_AUTH_EXPIRED, "msg": code.GetMsg(code.ERR_AUTH_EXPIRED), }) return } // 此處已經通過了, 可以把Claims中的有效資訊拿出來放入上下文使用 ctx.Set("username", claims.Username) ctx.Next() } }
/login不用中介軟體
中介軟體指定在authorizedrouter, 因此authorized下的所有路由都會使用此中介軟體
func main() { r := gin.Default() r.POST("/login", router.Login) authorized := r.Group("/auth") authorized.Use(jwt.JWTAuthMiddleware()) { authorized.GET("/getUserInfo", router.GetUserInfo) } r.Run(":8082") }
login請求獲取token
POST http://localhost:8082/login
把token放入getUserInfo請求
GET http://localhost:8082/auth/getUserInfo
完整的JWT登入還應該包括
通過上述流程你就能快速的在你的Go Gin專案中應用JWT能力
以上就是Go開發Gin專案新增jwt功能範例詳解的詳細內容,更多關於Go Gin專案新增jwt的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45