zoukankan      html  css  js  c++  java
  • golang goframe jwt token

    // token key
    var tokenKey = "5Gir3eXHbSwFWxyNaZfbulN0GdiObmvp"
    
    // 登录
    func Login(r *ghttp.Request) (interface{}, error) {
        username := r.GetString("username")//用户名
        u, e := g.DB().Table("*****").Where("username=?", g.Slice{username}).Fields("id,username,password").One()//数据库查询
        if e != nil {
            return nil, e
        }
        if u.IsEmpty() {
            return nil, errors.New("账号或密码错误")
        }
        // 密码验证
        if !validatePassword(r.GetString("password"), gconv.String(u["password"])) {
            return nil, errors.New("账号或密码错误")
        }
        // 生成 access token
        accessToken, e := CreateToken(&u, false)
        if e != nil {
            return nil, e
        }
        // 生成refresh token
        refreshToken, e := CreateToken(&u, true)
        if e != nil {
            return nil, e
        }
        return g.Map{
            "access_token":            accessToken["token"],
            "access_token_expire_at":  accessToken["exp"],
            "refresh_token":           refreshToken["token"],
            "refresh_token_expire_at": refreshToken["exp"],
        }, nil
    }
    
    // 使用refresh token 刷新 access token 和 refresh token
    func RefreshToken(r *ghttp.Request) (interface{}, error) {
        refreshTokenString := r.GetString("refresh_token") // 获取刷新token
        claims, err := ParseToken(refreshTokenString) // 解析token
        if err != nil {
            return nil, err
        }
        claimsMap := gconv.Map(claims) // token解析后的数据
        u, _ := g.DB().Table("*****").Where("id=?", g.Slice{claimsMap["id"]}).Fields("id,username,password").One()
        // 生成access_token
        accessToken, e := CreateToken(&u, false)
        if e != nil {
            return nil, e
        }
        // 生成refresh_token
        refreshToken, e := CreateToken(&u, true)
        if e != nil {
            return nil, e
        }
        return g.Map{
            "access_token":            accessToken["token"],
            "access_token_expire_at":  accessToken["exp"],
            "refresh_token":           refreshToken["token"],
            "refresh_token_expire_at": refreshToken["exp"],
        }, nil
    }
    
    // 使用access token 获取 refresh token
    func ReToken(r *ghttp.Request) (interface{}, error) {
        tokenString := GetHeaderToken(r)
        fmt.Println(tokenString)
        claims, err := ParseToken(tokenString)
        if err != nil {
            return nil, err
        }
        glog.Line().Println(claims)
        claimsMap := gconv.Map(claims)
        u, _ := g.DB().Table("*****").Where("id=?", g.Slice{claimsMap["id"]}).Fields("id,username,password").One()
        return CreateToken(&u, true)
    }
    
    // 获取header token
    func GetHeaderToken(r *ghttp.Request) string {
        headerAuthorization := r.Header.Get("Authorization")
        if headerAuthorization != "" {
            parts := strings.SplitN(headerAuthorization, " ", 2)
            if !(len(parts) == 2 && parts[0] == "Bearer") {
                return ""
            }
            return parts[1]
        }
        return ""
    }
    
    // 创建token
    func CreateToken(u *gdb.Record, isRe bool) (map[string]interface{}, error) {
        user := gconv.Map(u)
        expireAt := time.Now().Add(time.Hour).Unix()
        <!--如果是生成刷新token 加长时间-->
        if isRe {
            expireAt = time.Now().Add(time.Hour * 1000).Unix()
        }
        claims := jwt.MapClaims{
            "id":       gconv.String(user["id"]),
            "username": gconv.String(user["username"]),
            "exp":      expireAt,
            "iat":      xtime.GetNow().Unix(),
        }
        glog.Line().Println(claims)
        tokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
        token, err := tokenClaims.SignedString([]byte(tokenKey))
        return g.Map{
            "token": token,
            "exp":   expireAt,
        }, err
    }
    
    type Claims struct {
        Id       string `json:"id"`
        Username string `json:"username"`
        jwt.StandardClaims
    }
    
    // 解析token
    func ParseToken(token string) (interface{}, error) {
        tokenClaims, err := jwt.ParseWithClaims(token, &Claims{}, func(token *jwt.Token) (interface{}, error) {
            return []byte(tokenKey), nil
        })
        if err != nil {
            fmt.Println(err)
            return nil, errors.New("token 解析失败1")
        }
        claims, ok := tokenClaims.Claims.(*Claims)
        fmt.Println(claims)
        if !ok {
            return nil, errors.New("token 解析失败2")
        }
        if !tokenClaims.Valid {
            return nil, errors.New("token 已过期")
        }
        //if claims, ok := tokenClaims.Claims.(*Claims); ok && tokenClaims.Valid {
        //    return claims, nil
        //}
    
        return claims, err
    }
    
    // 验证密码
    func validatePassword(passwordString, hashedPasswordString string) bool {
        inputPassword := []byte(passwordString)
        hashedPassword := []byte(hashedPasswordString)
        e := bcrypt.CompareHashAndPassword(hashedPassword, inputPassword)
        if e != nil {
            return false
        }
        return true
    }
  • 相关阅读:
    《Programming WPF》翻译 第8章 1.动画基础
    一些被遗忘的设计模式
    《Programming WPF》翻译 第4章 数据绑定
    《Programming WPF》翻译 第3章 控件
    《Programming WPF》翻译 第5章 样式和控件模板
    《Programming WPF》翻译 第7章 绘图
    《Programming WPF》翻译 第9章 自定义控件
    《Programming WPF》翻译 第7章 绘图 (2)
    《Programming WPF》翻译 第8章 前言
    关于Debug和Release之本质区别
  • 原文地址:https://www.cnblogs.com/arvin-an/p/14665609.html
Copyright © 2011-2022 走看看