GoWeb开发-3.JWT

1.导入依赖库

go get -u github.com/dgrijalva/jwt-go

2.生成token

import (
    "fmt"
    "github.com/gin-gonic/gin"
    jwt "github.com/dgrijalva/jwt-go"
    "net/http"
    "time"
)
var jwtSecret=[]byte("secret")
type  Claims struct {
    
    
    Username string `json:"username"`
    Password string `json:"password"`
    jwt.StandardClaims
}

//生成token
func createToken(username,password string)(string,error)  {
    
    
    nowtime := time.Now()
    expireTime := nowtime.Add(3*time.Hour)

    claims := Claims{
    
    
        username,
        password,
        jwt.StandardClaims{
    
    
            ExpiresAt: expireTime.Unix(),
            Issuer: "gin-blog",
        },
    }
    //
    tokenClaims:=jwt.NewWithClaims(jwt.SigningMethodHS256,claims)
    token,err:=tokenClaims.SignedString(jwtSecret)
    return token,err
}

3.解析token

//解析token
// 验证token的函数
func ParseToken(token string)(*Claims,error){
    
    
    tokenClaims,err:=jwt.ParseWithClaims(token,&Claims{
    
    },func(token *jwt.Token)(interface{
    
    },error){
    
    
        return jwtSecret,nil
    })

    if tokenClaims!=nil{
    
    
        if claims,ok:=tokenClaims.Claims.(*Claims);ok && tokenClaims.Valid{
    
    
            return claims,nil
        }
    }
    //
    return nil,err
}

4.在gin的应用

登录,获取token

func authHandler(c *gin.Context) {
    
    
    // 用户发送用户名和密码过来
    var user Claims
    err := c.ShouldBind(&user)
    if err != nil {
    
    
        c.JSON(http.StatusOK, gin.H{
    
    
            "code": 2001,
            "msg":  "无效的参数",
        })
        return
    }
    fmt.Println(&user)
    // 校验用户名和密码是否正确
    if user.Username == "admin" && user.Password == "123456" {
    
    
        // 生成Token
        tokenString, _ := createToken(user.Username,user.Password)
        c.JSON(http.StatusOK, gin.H{
    
    
            "code": 2000,
            "msg":  "success",
            "data": gin.H{
    
    "token": tokenString},
        })
        return
    }
    c.JSON(http.StatusOK, gin.H{
    
    
        "code": 2002,
        "msg":  "鉴权失败",
    })
    return
}

r.POST("/auth", authHandler)

在其他接口加上解析token验证

// JWTAuthMiddleware 基于JWT的认证中间件
func JWTAuthMiddleware() func(c *gin.Context) {
    
    
    return func(c *gin.Context) {
    
    
        // 客户端携带Token有三种方式 1.放在请求头 2.放在请求体 3.放在URI
        // 这里假设Token放在Header的Authorization中,并使用Bearer开头
        // 这里的具体实现方式要依据你的实际业务情况决定
        authHeader := c.Request.Header.Get("token")
        if authHeader == "" {
    
    
            c.JSON(http.StatusOK, gin.H{
    
    
                "code": 2003,
                "msg":  "请求头中auth为空",
            })
            c.Abort()
            return
        }
        // 按空格分割
        //parts := strings.SplitN(authHeader, " ", 2)
        //if !(len(parts) == 2 && parts[0] == "Bearer") {
    
    
        //    c.JSON(http.StatusOK, gin.H{
    
    
        //        "code": 2004,
        //        "msg":  "请求头中auth格式有误",
        //    })
        //    c.Abort()
        //    return
        //}
        // parts[1]是获取到的tokenString,我们使用之前定义好的解析JWT的函数来解析它
        mc, err := ParseToken(authHeader)
        if err != nil {
    
    
            c.JSON(http.StatusOK, gin.H{
    
    
                "code": 2005,
                "msg":  "无效的Token",
            })
            c.Abort()
            return
        }
        // 将当前请求的username信息保存到请求的上下文c上
        c.Set("username", mc.Username)
        c.Next() // 后续的处理函数可以用过c.Get("username")来获取当前请求的用户信息
    }
}




    r.POST("/auth1",JWTAuthMiddleware(), func(c *gin.Context) {
    
    
        username := c.MustGet("username").(string)
        c.JSON(http.StatusOK, gin.H{
    
    
            "code": 2000,
            "msg":  "success",
            "data": gin.H{
    
    "username": username},
        })
    })

完整代码

package main

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

var jwtSecret=[]byte("secret")
type  Claims struct {
    
    
    Username string `json:"username"`
    Password string `json:"password"`
    jwt.StandardClaims
}

//生成token
func createToken(username,password string)(string,error)  {
    
    
    nowtime := time.Now()
    expireTime := nowtime.Add(3*time.Hour)

    claims := Claims{
    
    
        username,
        password,
        jwt.StandardClaims{
    
    
            ExpiresAt: expireTime.Unix(),
            Issuer: "gin-blog",
        },
    }
    //
    tokenClaims:=jwt.NewWithClaims(jwt.SigningMethodHS256,claims)
    token,err:=tokenClaims.SignedString(jwtSecret)
    return token,err
}

//解析token
// 验证token的函数
func ParseToken(token string)(*Claims,error){
    
    
    tokenClaims,err:=jwt.ParseWithClaims(token,&Claims{
    
    },func(token *jwt.Token)(interface{
    
    },error){
    
    
        return jwtSecret,nil
    })

    if tokenClaims!=nil{
    
    
        if claims,ok:=tokenClaims.Claims.(*Claims);ok && tokenClaims.Valid{
    
    
            return claims,nil
        }
    }
    //
    return nil,err
}

func authHandler(c *gin.Context) {
    
    
    // 用户发送用户名和密码过来
    var user Claims
    err := c.ShouldBind(&user)
    if err != nil {
    
    
        c.JSON(http.StatusOK, gin.H{
    
    
            "code": 2001,
            "msg":  "无效的参数",
        })
        return
    }
    fmt.Println(&user)
    // 校验用户名和密码是否正确
    if user.Username == "admin" && user.Password == "123456" {
    
    
        // 生成Token
        tokenString, _ := createToken(user.Username,user.Password)
        c.JSON(http.StatusOK, gin.H{
    
    
            "code": 2000,
            "msg":  "success",
            "data": gin.H{
    
    "token": tokenString},
        })
        return
    }
    c.JSON(http.StatusOK, gin.H{
    
    
        "code": 2002,
        "msg":  "鉴权失败",
    })
    return
}



// JWTAuthMiddleware 基于JWT的认证中间件
func JWTAuthMiddleware() func(c *gin.Context) {
    
    
    return func(c *gin.Context) {
    
    
        // 客户端携带Token有三种方式 1.放在请求头 2.放在请求体 3.放在URI
        // 这里假设Token放在Header的Authorization中,并使用Bearer开头
        // 这里的具体实现方式要依据你的实际业务情况决定
        authHeader := c.Request.Header.Get("token")
        if authHeader == "" {
    
    
            c.JSON(http.StatusOK, gin.H{
    
    
                "code": 2003,
                "msg":  "请求头中auth为空",
            })
            c.Abort()
            return
        }
        // 按空格分割
        //parts := strings.SplitN(authHeader, " ", 2)
        //if !(len(parts) == 2 && parts[0] == "Bearer") {
    
    
        //    c.JSON(http.StatusOK, gin.H{
    
    
        //        "code": 2004,
        //        "msg":  "请求头中auth格式有误",
        //    })
        //    c.Abort()
        //    return
        //}
        // parts[1]是获取到的tokenString,我们使用之前定义好的解析JWT的函数来解析它
        mc, err := ParseToken(authHeader)
        if err != nil {
    
    
            c.JSON(http.StatusOK, gin.H{
    
    
                "code": 2005,
                "msg":  "无效的Token",
            })
            c.Abort()
            return
        }
        // 将当前请求的username信息保存到请求的上下文c上
        c.Set("username", mc.Username)
        c.Next() // 后续的处理函数可以用过c.Get("username")来获取当前请求的用户信息
    }
}
func main() {
    
    
    r := gin.Default()
    r.POST("/auth", authHandler)
    r.POST("/auth1",JWTAuthMiddleware(), func(c *gin.Context) {
    
    
        username := c.MustGet("username").(string)
        c.JSON(http.StatusOK, gin.H{
    
    
            "code": 2000,
            "msg":  "success",
            "data": gin.H{
    
    "username": username},
        })
    })
    r.Run(":9090")
}

猜你喜欢

转载自blog.csdn.net/qq_25064691/article/details/120614767
jwt