doudou201701 2016-03-26 13:56
浏览 279
已采纳

Go和JWT-简单身份验证

I'm currently making an API (with go) and I'm working on the session part. After research about what to use for session, I found JWT really interesting.

However I'm not really sure to understand how to use it after some tutorials. So this is my idea:

func main() {

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

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

    http.ListenAndServe(":8080", router)

 }

After those requests handled, I create the differents functions.

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?                                  
    */
 }

Lot of tutorials on the web seems really hard but I just want something simple. I just want an handle package (code above) which work with a service package to have something like an engine token authentication.

A second point I'm not sure to understand is the saving of the token. If a user connects himself, then what would be best? Each time the user runs their app, the app connects itself and get a new token from saved information (user/password) or the app just save the token forever? And what about the server, is the token managed and saved automatically with JWT or do I have to put it in my sql database?

Thank for your help !

EDIT 1

Thank you ! So after I read your answer, I encapsulated my code (token.go) like it

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, ""
    }
 }

However, I got the following error: "token.go: undefined: myLookupKey" I looked on internet and I found an encapsulated function which have this prototype:

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

So what are the difference between my function and this one? How can I use this one?

Thanks !

  • 写回答

4条回答 默认 最新

  • doumizhi0809 2016-03-26 14:45
    关注

    To start, you need to import a JWT library in Golang (go get github.com/dgrijalva/jwt-go). You can find that library documentation in below link.

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

    Firstly, you need to create a token

    // 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)
    

    Secondly, parse that token

    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(":(")
    }
    

    Also, there are some examples for use JWT in GOlang like this https://github.com/slok/go-jwt-example

    EDIT-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.")
        }
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

悬赏问题

  • ¥15 装 pytorch 的时候出了好多问题,遇到这种情况怎么处理?
  • ¥20 IOS游览器某宝手机网页版自动立即购买JavaScript脚本
  • ¥15 手机接入宽带网线,如何释放宽带全部速度
  • ¥30 关于#r语言#的问题:如何对R语言中mfgarch包中构建的garch-midas模型进行样本内长期波动率预测和样本外长期波动率预测
  • ¥15 ETLCloud 处理json多层级问题
  • ¥15 matlab中使用gurobi时报错
  • ¥15 这个主板怎么能扩出一两个sata口
  • ¥15 不是,这到底错哪儿了😭
  • ¥15 2020长安杯与连接网探
  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么