【入门系列】Golang-JWT简单使用 | 青训营笔记

282 阅读2分钟

image.png 这是我参与「第三届青训营 -后端场」笔记创作活动的的第5篇笔记。

前言:在开发项目的时候,我们总会苦恼怎么鉴定用户并且判断能够使用哪些服务。在漫长的鉴权演化进程中,开发者们从Session到Cookie,最后演变成了Token。这篇文章不会对比这三个鉴权方式的优劣,而是通过golang-jwt模块向大家介绍jwt的用处。

什么是JWT?

JWT(Json Web Token)是一种开放的行业标准(RFC 7519)方法,用于在两方之间安全地表示声明。我们可以将JWT分成三个部分:令牌头(alg算法类型与type生成类型)、传递的信息与验证签名。 image.png

上图通过颜色标明各个字段存储的信息,而这段信息将会储存在客户端内,需要时可将令牌通过请求头上传至服务端,服务端解析后继续执行操作。

Golang-jwt模块将鉴权的操作最简化,以便于开发者更方便调用。譬如我们需要在JWT中存入生成时间和用户ID,生成和匹配代码如下:

import (
	"fmt"
	"time"

	"github.com/golang-jwt/jwt"
)

var Secret = []byte("TestSecret")

// 签发token, 仅传入userID, token令牌中仅包含id和创建时间
func Sign(userID uint) (string, error) {
    // 使用HS256生成token
    token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
        // 存入信息
        "id":  userID,
        "nbf": time.Now().Unix(),
    })

    // 加密
    tokenString, err := token.SignedString([]byte(Secret))
    return tokenString, err
}

// 解析token, 仅传入token字符串, 仅判断是否转换成功与令牌是否超时
func Parse(tokenString string) (uint, error) {
    // 通过JWT令牌头获取加密算法
    token, err := jwt.Parse(tokenString, func(t *jwt.Token) (interface{}, error) {
        if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok {
            return nil, fmt.Errorf("加密方式错误: %v", t.Header["alg"])
        }
	return []byte(Secret), nil
    })
    if err != nil {
        fmt.Println("token获取错误")
    }
    // 解析token存储的消息
    claims, ok := token.Claims.(jwt.MapClaims)
    if !(ok && token.Valid) {
        fmt.Println("token解析错误, 请重新登陆获取")
    } else {
        fmt.Println(claims["id"], claims["nbf"])
    }
}

在解析出用户的ID后,我们可以通过ID从数据库中查找相应的用户信息。而且只要密钥不被泄露,这个令牌的安全系数也非常高。更重要的是,这个令牌只会存在于客户端中,不会消耗服务端的存储。

希望这篇文章能够快速上手JWT的应用!