go get github.com/dgrijalva/jwt-go
// 定义一个密钥
var jwtKey = []byte("define_a_secret")
// 定义Claims
type Claims struct {
UserId uint
jwt.StandardClaims
}
type User struct {
ID uint `form:"id"`
Username string `form:"username"`
Password string `form:"password"`
}
// 产生JWT
func GenerateToken(id uint) (tokenString string) {
// user := User{ID: id, UserName: "张三"}

expireTime := time.Now().Add(7 * 24 * time.Hour).Unix()
issueTime := time.Now().Unix()


claims := &Claims{
// UserId: user.ID,
UserId: id,
StandardClaims: jwt.StandardClaims{
// token过期时间
ExpiresAt: expireTime,
// 发放时间
IssuedAt: issueTime,
// 发放人
Issuer: "Issuer",
// 签名主题
Subject: "user token",
},
}
// 使用指定的签名方法创建签名对象
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
//使用指定的secret签名并获得完整的编码后的字符串token
tokenString, err := token.SignedString(jwtKey)
if err != nil {
fmt.Println(err)
return
}
// fmt.Println(tokenString)


return tokenString
}
// 解析JWT
func ParseToken(tokenString string) (*jwt.Token, *Claims, error) {
claims := &Claims{}
token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (i interface{}, err error) {
return jwtKey, nil
})
return token, claims, err
}
package main


import (
"github.com/gin-gonic/gin"
)


func main() {
r := gin.Default()


// 登录,验证username,password,产生token
r.POST("/login", loginHandle)

r.Run(":8080")
}
// loginHandle
func loginHandle(c *gin.Context) {
// form表单提交username和password
username := c.PostForm("username")
password := c.PostForm("password")


// 认证成功
if username == "zhangsan" && password == "123456" {
// token
tokenString := GenerateToken(222)
c.JSON(200, gin.H{
"code": http.StatusOK,
"msg": "OK",
"token": tokenString,
})
} else {
c.JSON(http.StatusOK, gin.H{
"code": http.StatusUnauthorized,
"msg": "Unauthorized",
"token": nil,
})
  }
}
  // 访问用户资源(要求必须认证的用户才能访问)
  r.GET("/users", usersHandle)
// usersHandle
func usersHandle(c *gin.Context) {
// userId, ok := c.Get("userId")
// if !ok {
// return
// }
// c.String(http.StatusOK, userId)


// 查询用户数据,返回


c.String(http.StatusOK, "users")
}

■ ■■■■


6. JWT认证中间件

现在定义一个基于JWT的认证中间件来保护您的资源。
// 认证中间件
func AuthMiddleWare() gin.HandlerFunc {
return func (ctx *gin.Context) {
// 假设Token放在Header的Authorization中,并使用Bearer开头
tokenString := ctx.GetHeader("Authorization")


if tokenString == "" || !strings.HasPrefix(tokenString, "Bearer ") {
ctx.JSON(http.StatusUnauthorized, gin.H{
"code": http.StatusUnauthorized,
"msg": "权限不足",
})


ctx.Abort()


return
}


// 去掉Bearer
tokenString = tokenString[7:]


// 使用之前定义好的解析JWT的函数 ParseToken 来解析它
token, claims, err := ParseToken(tokenString)
if err != nil || !token.Valid {
ctx.JSON(http.StatusUnauthorized, gin.H{
"code": http.StatusUnauthorized,
"msg": "权限不足",
})


ctx.Abort()


return
}


// 验证通过,获取claim中的userid
    userId := claims.UserId


ctx.Set("userId", userId)
ctx.Next()
}
}

将中间件应用到需要受保护的资源:
  // 访问用户资源(要求必须认证的用户才能访问)
r.GET("/users", AuthMiddleWare(), usersHandle)


至此,所有的逻辑都已完成。

■ ■■■■


7. 整合代码

将上面所有的逻辑整合为如下完整代码:
package main


import (
"fmt"
"net/http"
"strings"
"time"


"github.com/dgrijalva/jwt-go"
"github.com/gin-gonic/gin"
)


// 定义Claims
type Claims struct {
UserId uint
jwt.StandardClaims
}


type User struct {
ID uint `form:"id"`
Username string `form:"username"`
Password string `form:"password"`
}


// 定义一个密钥
var jwtKey = []byte("define_a_secret")


func main() {

r := gin.Default()


// 登录,验证username,password,产生token
r.POST("/login", loginHandle)

// 访问用户资源(要求必须认证的用户才能访问)
r.GET("/users", AuthMiddleWare(), usersHandle)

r.Run(":8080")


}


// usersHandle
func usersHandle(c *gin.Context) {
// userId, ok := c.Get("userId")
// if !ok {
// return
// }
// c.String(http.StatusOK, userId)


// 查询用户数据,返回


c.String(http.StatusOK, "users")
}


// loginHandle
func loginHandle(c *gin.Context) {
// form表单提交username和password
username := c.PostForm("username")
password := c.PostForm("password")


// 认证成功
if username == "zhangsan" && password == "123456" {
// token
tokenString := GenerateToken(222)
c.JSON(200, gin.H{
"code": http.StatusOK,
"msg": "OK",
"token": tokenString,
})
} else {
c.JSON(http.StatusOK, gin.H{
"code": http.StatusUnauthorized,
"msg": "Unauthorized",
"token": nil,
})
}


}


// 产生JWT
func GenerateToken(id uint) (tokenString string) {
// user := User{ID: id, UserName: "张三"}

expireTime := time.Now().Add(7 * 24 * time.Hour).Unix()
issueTime := time.Now().Unix()


claims := &Claims{
// UserId: user.ID,
UserId: id,
StandardClaims: jwt.StandardClaims{
// token过期时间
ExpiresAt: expireTime,
// 发放时间
IssuedAt: issueTime,
// 发放人
Issuer: "Issuer",
// 签名主题
Subject: "user token",
},
}
// 使用指定的签名方法创建签名对象
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
//使用指定的secret签名并获得完整的编码后的字符串token
tokenString, err := token.SignedString(jwtKey)
if err != nil {
fmt.Println(err)
return
}
// fmt.Println(tokenString)


return tokenString
}


// 解析JWT
func ParseToken(tokenString string) (*jwt.Token, *Claims, error) {
claims := &Claims{}
token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (i interface{}, err error) {
return jwtKey, nil
})
return token, claims, err
}


// 认证中间件
func AuthMiddleWare() gin.HandlerFunc {
return func (ctx *gin.Context) {
// 假设Token放在Header的Authorization中,并使用Bearer开头
tokenString := ctx.GetHeader("Authorization")


if tokenString == "" || !strings.HasPrefix(tokenString, "Bearer ") {
ctx.JSON(http.StatusUnauthorized, gin.H{
"code": http.StatusUnauthorized,
"msg": "权限不足",
})


ctx.Abort()


return
}


// 去掉Bearer
tokenString = tokenString[7:]


// 使用之前定义好的解析JWT的函数 ParseToken 来解析它
token, claims, err := ParseToken(tokenString)
if err != nil || !token.Valid {
ctx.JSON(http.StatusUnauthorized, gin.H{
"code": http.StatusUnauthorized,
"msg": "权限不足",
})


ctx.Abort()


return
}


// 验证通过,获取claim中的userid
    userId := claims.UserId


ctx.Set("userId", userId)
ctx.Next()
}
}