我目前正在制作一个API(使用Go),我正在处理会话部分. 在研究了会话使用的内容之后,我发现JWT真的很有趣.

然而,经过一些教程之后,我不太确定如何使用它.

func main() {

    router := mux.NewRouter().StrictSlash(true)

    router.HandleFunc("/login", login)
    router.HandleFunc("/logout", logout)
    router.HandleFunc("/register", register)

    http.ListenAndServe(":8080", router)

 }

处理完这些请求后,我创建了不同的函数.

func login(w http.ResponseWriter, r *http.Request) {
    /*                                                                                                                                                                                                   
    Here I just have to search in my database (SQL, I know how to do it). If the user is registered, I create a token and give it to him, but how can I do it?                                           
    */
 }

 func logout(w http.ResponseWriter, r *http.Request) {
    /*                                                                                                                                                                                                   
    I get a token and stop/delete it?                                                                                                                                                                    
    */
 }

 func register(w http.ResponseWriter, r *http.Request) {
    /*                                                                                                                                                                                                   
    I search if the user isn't register and then, if it isn't, I create a user in the database (I know how to do it). I connect him but again, how to make a new token?                                  
    */
 }

网上的很多教程似乎真的很难,但我只想要一些简单的东西.我只想要一个句柄包(上面的代码),它与服务包一起工作,以具有类似于引擎令牌身份验证的东西.

我不太明白的第二点是令牌的保存. 如果用户自己连接,那么什么才是最好的呢?用户每次运行他们的应用程序时,应用程序会自行连接并从保存的信息(用户/密码)中获得新的令牌,还是应用程序只是将令牌永久保存?那么服务器呢,令牌是使用JWT自动管理和保存的,还是必须将其放入我的SQL数据库中呢?

谢谢你的帮助!

EDIT 1

谢谢你!因此,在我阅读了您的答案之后,我将我的代码(token.go)封装为

package services

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

var tokenEncodeString string = "something"

func createToken(user models.User) (string, error) {
    // create the token                                                                                                                                                                                  
    token := jwt.New(jwt.SigningMethodHS256)

    // set some claims                                                                                                                                                                                   
    token.Claims["username"] = user.Username;
    token.Claims["password"] = user.Password;
    token.Claims["exp"] = time.Now().Add(time.Hour * 72).Unix()

    //Sign and get the complete encoded token as string                                                                                                                                                  
    return (token.SignedString(tokenEncodeString))
}

func parseToken(unparsedToken string) (bool, string) {
    token, err := jwt.Parse(unparsedToken, func(token *jwt.Token) (interface{}, error) {
            // Don't forget to validate the alg is what you expect:                                                                                                                                      
            if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
                    return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
            }
            return myLookupKey(token.Header["kid"]), nil
    })

    if err == nil && token.Valid {
            return true, unparsedToken
    } else {
            return false, ""
    }
 }

但是,我收到以下错误:"token.go:unfined:myLookupKey" 我在互联网上查找,发现了一个封装的函数,其原型如下:

func ExampleParse(myToken string, myLookupKey func(interface{}) (interface{}, error)) {
 /* same code in my func parseToken() */
}

那么我的功能和这个有什么不同呢?这件怎么用呢?

谢谢!

推荐答案

首先,您需要在Golang中导入一个JWT库(请访问github.com/dgrijalva/jwt-go).您可以在下面的链接中找到该库文档.

https://github.com/dgrijalva/jwt-go

首先,您需要创建一个令牌

// Create the token
token := jwt.New(jwt.SigningMethodHS256)
// Set some claims
token.Claims["foo"] = "bar"
token.Claims["exp"] = time.Now().Add(time.Hour * 72).Unix()
// Sign and get the complete encoded token as a string
tokenString, err := token.SignedString(mySigningKey)

其次,解析该令牌

token, err := jwt.Parse(myToken, func(token *jwt.Token) (interface{}, error) {
    // Don't forget to validate the alg is what you expect:
    if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
        return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
    }
    return myLookupKey(token.Header["kid"]), nil
})

if err == nil && token.Valid {
    deliverGoodness("!")
} else {
    deliverUtterRejection(":(")
}

此外,还有一些在GOlang中使用JWT的示例,如下面的https://github.com/slok/go-jwt-example

编辑-1

package main

import (
    "fmt"
    "time"

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

const (
    mySigningKey = "WOW,MuchShibe,ToDogge"
)

func main() {
    createdToken, err := ExampleNew([]byte(mySigningKey))
    if err != nil {
        fmt.Println("Creating token failed")
    }
    ExampleParse(createdToken, mySigningKey)
}

func ExampleNew(mySigningKey []byte) (string, error) {
    // Create the token
    token := jwt.New(jwt.SigningMethodHS256)
    // Set some claims
    token.Claims["foo"] = "bar"
    token.Claims["exp"] = time.Now().Add(time.Hour * 72).Unix()
    // Sign and get the complete encoded token as a string
    tokenString, err := token.SignedString(mySigningKey)
    return tokenString, err
}

func ExampleParse(myToken string, myKey string) {
    token, err := jwt.Parse(myToken, func(token *jwt.Token) (interface{}, error) {
        return []byte(myKey), nil
    })

    if err == nil && token.Valid {
        fmt.Println("Your token is valid.  I like your style.")
    } else {
        fmt.Println("This token is terrible!  I cannot accept this.")
    }
}

Go相关问答推荐

Golang Cososdb-gremlin连接

如何获得与cksum相同的CRC 32?

验证访问令牌(密钥罩)

如何将文件从AWS S3存储桶复制到Azure BLOB存储

正则表达式模式,确保至少一个字符与其他条件一起存在

如何在golang中使用viper获取对象的配置数组?

Docker 执行失败并显示cmd/ENTRYPOINT 中的命令未找到

golang / urfave.cli:无法手动设置标志

在密钥不存在时处理 PATCH 部分更新

从Go中的随机日期开始以天为单位获取时间

整理时转换值

SSH 代理,数据包长度错误

不能使用 mockDB(*MockDB 类型的变量)作为 struct 文字中的 *gorm.DB 值

go-libp2p - 从流中接收字节

golang pic.ShowImage 为什么它不生成图像而是向我发送base64值

如何在 GORM 中获取字段值

使用 Go 读取 TOML 文件时结果为空

当 git clone 工作时,Go mod tidy 在私有存储库上失败

Go 使用 struct 作为接口而不实现所有方法

Go 1.18 泛型如何使用接口定义新的类型参数