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)

  • 相关阅读:
    进程池,线程池,协程,gevent模块,协程实现单线程服务端与多线程客户端通信,IO模型
    线程相关 GIL queue event 死锁与递归锁 信号量l
    生产者消费者模型 线程相关
    进程的开启方式 进程的join方法 进程间的内存隔离 其他相关方法 守护进程 互斥锁
    udp协议 及相关 利用tcp上传文件 socketserver服务
    socket套接字 tcp协议下的粘包处理
    常用模块的完善 random shutil shevle 三流 logging
    day 29 元类
    Django入门
    MySQL多表查询
  • 原文地址:https://www.cnblogs.com/lrj567/p/6209872.html
Copyright © 2011-2022 走看看