美文网首页js css html
GO语言gin框架实战-02-Jwt和登录认证

GO语言gin框架实战-02-Jwt和登录认证

作者: 玄德公笔记 | 来源:发表于2022-10-24 23:35 被阅读0次

    1. 相关函数

    创建如下函数:

    • 登录函数:登录接口调用该函数
    • 身份验证:其他函数调用该函数,用token判断身份是否合法
    • 刷新token:登录接口调用该函数,如果token验证通过则发放新token
    • 验证token:需要验证身份的服务调用该函数判断token是否合法
    • 生成token: 其他函数调用该函数,用以生成新token
    package router
    
    import (
        "github.com/dgrijalva/jwt-go"
        "github.com/gin-gonic/gin"
        "time"
    )
    
    type LoginInfo struct {
        UserName string  `json:"user_name"`
        Password string `json:"password"`
    }
    
    
    type JWTClaims struct { // token里面添加用户信息,验证token后可能会用到用户信息
        jwt.StandardClaims
        UserID      int      `json:"user_id"`
        Password    string   `json:"password"`
        Username    string   `json:"username"`
        FullName    string   `json:"full_name"`
        Permissions []string `json:"permissions"`
    }
    
    var (
        Secret     = "LiuBei" // 加盐
        ExpireTime = 3600*24        // token有效期
    )
    
    //登录
    func Login(c *gin.Context) {
    
        var loginRequest LoginInfo
        err := c.Bind(&loginRequest)
        if err != nil {
            c.JSON(400,err.Error())
            return
        }
        //模拟用户认证
        if loginRequest.UserName != "liuBei" || loginRequest.Password != "liubei@161" {
            c.JSON(401,gin.H{"err":"账号或密码错误"})
            return
        }
    
        claims := &JWTClaims{
            UserID:      1,
            Username:    loginRequest.UserName,
            Password:    loginRequest.Password,
            FullName:    loginRequest.UserName,
            Permissions: []string{},
        }
        claims.IssuedAt = time.Now().Unix()
        claims.ExpiresAt = time.Now().Add(time.Second * time.Duration(ExpireTime)).Unix()
        signedToken,err:=getToken(claims)
    
        if err!=nil {
            c.JSON(400,err.Error())
            return
        }
        //fmt.Printf(signedToken)
        c.JSON(200, gin.H{"token": signedToken})
    }
    
    
    //身份验证
    
    func Verify(c *gin.Context)(result bool,userName string,err error) {
        strToken,err := c.Cookie("Crow")
        if strToken == ""{
            result = false
            return result,"",nil
        }
        claim,err := verifyAction(strToken)
        if err != nil {
            result = false
            return result,"",nil
        }
        result = true
        userName = claim.Username
        return result,userName,nil
    }
    
    //刷新token
    func Refresh(c *gin.Context) {
        strToken,err := c.Cookie("Crow")
        claims,err := verifyAction(strToken)
        if err != nil {
            c.JSON(400,gin.H{"err":err.Error()})
            return
        }
        claims.ExpiresAt = time.Now().Unix() + (claims.ExpiresAt - claims.IssuedAt)
        signedToken,err:=getToken(claims)
        if err!=nil{
            c.JSON(400,gin.H{"err":err.Error()})
            return
        }
        c.JSON(200,gin.H{"data": signedToken })
    }
    
    //验证token是否存在,存在则获取信息
    func verifyAction(strToken string) (claims *JWTClaims,err error) {
        token, err := jwt.ParseWithClaims(strToken, &JWTClaims{}, func(token *jwt.Token) (interface{}, error) {
            return []byte(Secret), nil
        })
        if err != nil {
            return nil, err
        }
        claims, ok := token.Claims.(*JWTClaims)
        if !ok {
            return nil, err
        }
        if err := token.Claims.Valid(); err != nil {
            return nil, err
        }
        return claims, nil
    }
    
    //生成token
    func getToken(claims *JWTClaims)(signedToken string,err error){
        token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
        signedToken, err = token.SignedString([]byte(Secret))
        if err != nil {
            return "",err
        }
        return signedToken,nil
    }
    
    
    

    2. router对其调用

        loginGroup := r.Group("/api/v1/login")
        {
            loginGroup.POST("/", Login) //登录服务器
            loginGroup.POST("/refresh", Refresh) //生成新token
        }
    

    3. 其他接口身份验证

    以上一章k8s服务的 查询deployment接口为例,开头添加如下内容:

    
    func GetDeployment(c *gin.Context)  {
        //身份认证
        checkUser,_,err := Verify(c) //第二个值是用户名,这里没有使用
        if err != nil{
            c.JSON(400,gin.H{"err":err.Error()})
            return
        }
        if checkUser == false {
            c.JSON(400,gin.H{"err":"身份认证失败"})
            return
        }
    
        //查询开始
        ……
    }
    

    4. postman 测试

    4.1 测试登录接口

    image.png

    登录成功获取到token。

    4.2 postman设置Cookies

    image.png

    注意:Crow这个 key的名字是刚才我们在代码里边指定的

    4.3 其他接口调用身份验证测试

    • 成功的情况

    我们可以看到Headers里多了我们刚才添加的Cookie,是我们刚才添加的Crow

    image.png
    • 验证失败的情况

    我们把刚才的Cookie改成错的,然后再测试:

    image.png

    相关文章

      网友评论

        本文标题:GO语言gin框架实战-02-Jwt和登录认证

        本文链接:https://www.haomeiwen.com/subject/jylnzrtx.html