Golang JWT使用

在環境GOPATH/src 裏:

           go get github.com/dgrijalva/jwt-go

思路:

          1.在登陸時,創建Tocken

          2. 再次請求時,驗證TOcken

實體代碼

import   "github.com/dgrijalva/jwt-go"
// 建立統一標準需求 實體
type OceanClainms struct {
    Username string `json:username`
    Uid uint `json:"uid"`
    // JWT 標準需求
    jwt.StandardClaims
}
// 用戶登陸實體
type User struct {
     Uid uint
     UserName string
     UserPass string
}
// 登陸返回的實體
type ResultMessage struct {
Message string
Tocken string
}
 
// 登陸操作
func Login(UserName string,passward string) ResultMessage{
    var result ResultMessage
    var user User
    user.UserName="zx"
    user.UserPass="123"
    if user.UserName==UserName && user.UserPass==passward{  // 登陸成功
        // 登陸成功 創建Tocken
        tocken,err:=CreateTocken(user.UserName,user.Uid)
        if err!=nil{
            result.Message=err.Error()
        }else {
            result.Message="sucess"
            result.Tocken=tocken
        }
    }else {
        result.Message=errors.New("用戶名或密碼錯誤!").Error()
    }
    return result
}

// Base64 加密串
var key ="c2RmZGZzZGN4Y3g1MzMqJWRGZmQp"
// 創建Tocken
func CreateTocken(UserName string,Uid uint) (string,error){
    clims := OceanClainms{Username:UserName ,Uid:Uid, StandardClaims:jwt.StandardClaims{
        //  過期時間
        ExpiresAt: time.Now().Add(time.Hour*24*7).Unix(),
        //  生成時間
        IssuedAt: time.Now().Unix(),
        // 生成者
        Issuer: "Service",
        },
    }
    tonken :=jwt.NewWithClaims(jwt.SigningMethodHS256,clims)
// 注意 這裏的Key 是Base64加密字符串 tonkenStr,err:
= tonken.SignedString([]byte(key)) if err!=nil{ // TODO } return tonkenStr,err }

建立驗證Tocken 中間件,當用戶登後做其他請求時,必須傳遞Tocken在中間件裏做驗證,驗證成功方能請求

// Tocken 驗證中間件
func AuthMiddleware() gin.HandlerFunc{
    return func(context *gin.Context) {
        // 獲取傳遞過來的Tocken
        tokenString :=context.GetHeader("Authorization")
        if tokenString ==""|| tokenString[0:7]!="Bearer "{
            context.JSON(http.StatusUnauthorized,gin.H{
                "messsage":"Token驗證失敗",
            })
            context.Abort()
            return
        }
        // 解析Tocker
        tonken,clains,err:=ParseTocker(tokenString[7:])
        if err!=nil ||!tonken.Valid{  // 判斷Tocken是否有效
            context.JSON(http.StatusUnauthorized,gin.H{
                "messsage":"Tocken無效",
            })
            context.Abort()
            return
        }
        context.Set("user",clains.Username)
        context.Next()
    }
}
// 解析Tocken
// tonkenString  Tocken字符串
func ParseTocker(tonkenString string) (*jwt.Token,OceanClainms,error){
 clains :=OceanClainms{}
 tonken,err :=jwt.ParseWithClaims(tonkenString,&clains,func(token *jwt.Token) (interface{},error){
           return []byte(key),nil
    })
 return tonken,clains,err
}

main方法 :登陸成功生成Tocken, 除登陸外的請求皆加Tocken驗證

package main

import (
    "errors"
    "github.com/dgrijalva/jwt-go"
    "github.com/gin-gonic/gin"
    "net/http"
    "time"
)

func main()  {
    engin :=gin.Default()
    // 登陸請求成功後返回Tocken
    engin.GET("/login", func(c *gin.Context) {
        var user User
        err:=c.ShouldBind(&user)   // 將參數轉爲User對像
        if err!=nil{
            c.JSON(http.StatusBadRequest,"請求錯誤:參數名稱不對")
            return
        }
        result:= Login(user.UserName,user.UserPass) // 獲取返回信息
        c.JSON(http.StatusOK,gin.H{
            "message":result.Message,
            "Tocken": result.Tocken,
        })
    })
    // 登陸後所有的請求,加入中間件驗證Tocken
    engin.GET("/add",AuthMiddleware(), func(context *gin.Context) {
        context.JSON(http.StatusOK,gin.H{"request":"OK"})
    })
    engin.Run(":1200")
}

完整代碼

package main

import (
    "errors"
    "github.com/dgrijalva/jwt-go"
    "github.com/gin-gonic/gin"
    "net/http"
    "time"
)
// Base64 加密串
var key ="c2RmZGZzZGN4Y3g1MzMqJWRGZmQp"
// 建立統一標準需求 實體
type OceanClainms struct {
    Username string `json:username`
    Uid uint `json:"uid"`
    // JWT 標準需求
    jwt.StandardClaims
}
// 用戶登陸實體
type User struct {
     Uid uint
     UserName string
     UserPass string
}

// 創建Tocken
func CreateTocken(UserName string,Uid uint) (string,error){
    clims := OceanClainms{Username:UserName ,Uid:Uid, StandardClaims:jwt.StandardClaims{
        //  過期時間
        ExpiresAt: time.Now().Add(time.Hour*24*7).Unix(),
        //  生成時間
        IssuedAt: time.Now().Unix(),
        // 生成者
        Issuer: "Service",
        },
    }
    tonken :=jwt.NewWithClaims(jwt.SigningMethodHS256,clims)
    tonkenStr,err:= tonken.SignedString([]byte(key))
    if err!=nil{
        // TODO
    }
    return tonkenStr,err
}

// 解析Tocken
// tonkenString  Tocken字符串
func ParseTocker(tonkenString string) (*jwt.Token,OceanClainms,error){
 clains :=OceanClainms{}
 tonken,err :=jwt.ParseWithClaims(tonkenString,&clains,func(token *jwt.Token) (interface{},error){
           return []byte(key),nil
    })
 return tonken,clains,err
}

// 登陸返回的實體
type ResultMessage struct {
    Message string
    Tocken string
}

// 登陸操作
func Login(UserName string,passward string) ResultMessage{
    var result ResultMessage
    var user User
    user.UserName="zx"
    user.UserPass="123"
    if user.UserName==UserName && user.UserPass==passward{  // 登陸成功
        // 登陸成功 創建Tocken
        tocken,err:=CreateTocken(user.UserName,user.Uid)
        if err!=nil{
            result.Message=err.Error()
        }else {
            result.Message="sucess"
            result.Tocken=tocken
        }
    }else {
        result.Message=errors.New("用戶名或密碼錯誤!").Error()
    }
    return result
}

// Tocken 驗證中間件
func AuthMiddleware() gin.HandlerFunc{
    return func(context *gin.Context) {
        // 獲取傳遞過來的Tocken
        tokenString :=context.GetHeader("Authorization")
        if tokenString ==""|| tokenString[0:7]!="Bearer "{
            context.JSON(http.StatusUnauthorized,gin.H{
                "messsage":"Token驗證失敗",
            })
            context.Abort()
            return
        }
        // 解析Tocker
        tonken,clains,err:=    ParseTocker(tokenString[7:])
        if err!=nil ||!tonken.Valid{  // 判斷Tocken是否有效
            context.JSON(http.StatusUnauthorized,gin.H{
                "messsage":"Tocken無效",
            })
            context.Abort()
            return
        }
        context.Set("user",clains.Username)
        context.Next()
    }
}

func main()  {
    engin :=gin.Default()
    // 登陸請求成功後返回Tocken
    engin.GET("/login", func(c *gin.Context) {
        var user User
        err:=c.ShouldBind(&user)   // 將參數轉爲User對像
        if err!=nil{
            c.JSON(http.StatusBadRequest,"請求錯誤:參數名稱不對")
            return
        }
        result:= Login(user.UserName,user.UserPass) // 獲取返回信息
        c.JSON(http.StatusOK,gin.H{
            "message":result.Message,
            "Tocken": result.Tocken,
        })
    })
    // 加入中間件驗證Tocken
    engin.GET("/add",AuthMiddleware(), func(context *gin.Context) {
        context.JSON(http.StatusOK,gin.H{"request":"OK"})
    })
    engin.Run(":1200")
}

 PostMan請求

 

 

 

 上面是Tocken不正確的結果,下面是正確Tocken的結果

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章