zoukankan      html  css  js  c++  java
  • beego应用做纯API后端如何使用jwt实现无状态权限验证

    jwt是什么,可以百度下其它文章,我原来看到一个讲的详细的,现在找不到了。先简单介绍下我个人的理解,就是一个token,只不过通过加密解密的手段,能让这一串字符带有一些简单的信息。这样解密jwt后不用查数据库,最常用的例子,保存用户权限,再多层的权限,其实只用一个数字,转换成二进制,每一位代表一种权限。类似这样的使用,还有保存session的key,通过该值查session就能获取更丰富的资料,用来保存用户状态也是可以的。

    下面介绍下我的一个golang项目中使用beego框架做纯API接口使用jwt的方法。

    首先用到jwt函数的go文件都要引入这个库

    import (
      "github.com/dgrijalva/jwt-go"
    )

     
    登录函数中登录成功把jwt字符串发给客户端,客户端需要保存起来比如localStorage中,访问别的API时加到header里面, 注意这个里面exp是必须要的,生命周期。其他都是根据自己需求添加的键值对。。
    if passwd == user.Password {
    
                // 带权限创建令牌
                claims := make(jwt.MapClaims)
                claims["username"] = username
                if username == "admin" {
                    claims["admin"] = "true"
                } else {
                    claims["admin"] = "false"
                }
                claims["exp"] = time.Now().Add(time.Hour * 480).Unix() //20天有效期,过期需要重新登录获取token
                token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
    
                // 使用自定义字符串加密 and get the complete encoded token as a string
                tokenString, err := token.SignedString([]byte("mykey"))
                if err != nil {
                    beego.Error("jwt.SignedString:", err)
                    this.RetError(errSystem)
                    return
                }
                this.Data["json"] = map[string]interface{}{"status": 200, "message": "login success ", "moreinfo": tokenString}
            } else {
                this.Data["json"] = map[string]interface{}{"status": 400, "message": "login failed ", "moreinfo": time.Now().Format("2006-01-02 15:04:05")}
            }


    baseControler写这个函数,别的函数全部调用这个做权限认证
    // ParseToken parse JWT token in http header.
    func (c *BaseController) ParseToken() (t *jwt.Token, e *ControllerError) {
        authString := c.Ctx.Input.Header("Authorization")
        beego.Debug("AuthString:", authString)
    
        kv := strings.Split(authString, " ")
        if len(kv) != 2 || kv[0] != "Bearer" {
            beego.Error("AuthString invalid:", authString)
            return nil, errInputData
        }
        tokenString := kv[1]
    
        // Parse token
        token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
            return []byte("mykey"), nil
        })
        if err != nil {
            beego.Error("Parse token:", err)
            if ve, ok := err.(*jwt.ValidationError); ok {
                if ve.Errors&jwt.ValidationErrorMalformed != 0 {
                    // That's not even a token
                    return nil, errInputData
                } else if ve.Errors&(jwt.ValidationErrorExpired|jwt.ValidationErrorNotValidYet) != 0 {
                    // Token is either expired or not active yet
                    return nil, errExpired
                } else {
                    // Couldn't handle this token
                    return nil, errInputData
                }
            } else {
                // Couldn't handle this token
                return nil, errInputData
            }
        }
        if !token.Valid {
            beego.Error("Token invalid:", tokenString)
            return nil, errInputData
        }
        beego.Debug("Token:", token)
    
        return token, nil
    }
    其他API代码片段
    token, e := this.ParseToken()
        if e != nil {
            this.RetError(e)
            return
        }
        claims, ok := token.Claims.(jwt.MapClaims)
        if !ok {
            this.RetError(errPermission)
            return
        }
    var user string = claims["username"].(string)

  • 相关阅读:
    再也不想更新的沙雕错误合集
    「HNSDFZ暑期集训 测试1」「LuoguT36488」 连连看
    「HNSDFZ暑期集训 测试1」「LuoguT36485」 括号(贪心
    「UVA524」 Prime Ring Problem 质数环
    「LuoguP2434」 [SDOI2005]区间(贪心
    「LuoguP4047」 [JSOI2010]部落划分
    「LuoguP1281」 书的复制(贪心
    「LuoguP1238」 走迷宫
    「LuoguP4753」濑 River Jumping(贪心
    BZOJ4400 TJOI2012桥(最短路+线段树)
  • 原文地址:https://www.cnblogs.com/lrj567/p/6209872.html
Copyright © 2011-2022 走看看