在环境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的结果