Golang JWT使用
阿新 • • 發佈:2020-08-06
在環境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")
}