web-dev-qa-db-de.com

Go und JWT - Einfache Authentifizierung

Ich mache gerade eine API (mit go) und arbeite an dem Sitzungsteil . Nachdem ich herausgefunden hatte, was für eine Sitzung verwendet werden soll, fand ich JWT wirklich interessant.

Ich bin mir jedoch nicht wirklich sicher, wie ich es nach einigen Tutorials verwenden kann ... Das ist meine Idee:

func main() {

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

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

    http.ListenAndServe(":8080", router)

 }

Nachdem diese Anforderungen bearbeitet wurden, erstelle ich die verschiedenen Funktionen.

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

Viele Tutorials im Web scheinen sehr schwer zu sein, aber ich möchte nur etwas einfaches. Ich möchte nur ein Handle-Paket (Code oben), das mit einem Service-Paket zusammenarbeitet, um so etwas wie eine Engine-Token-Authentifizierung zu haben.

Ein zweiter Punkt, den ich nicht genau verstehen kann, ist das Speichern des Tokens. Wenn ein Benutzer sich verbindet, was wäre dann am besten? Jedes Mal, wenn der Benutzer seine App ausführt, stellt die App eine eigene Verbindung her und erhält ein neues Token aus den gespeicherten Informationen (Benutzer/Kennwort) oder die App speichert das Token einfach für immer? Und was ist mit dem Server, wird das Token automatisch mit JWT verwaltet und gespeichert oder muss ich es in meine SQL-Datenbank aufnehmen?

Danke für deine Hilfe !

BEARBEITEN 1

Vielen Dank ! Nachdem ich Ihre Antwort gelesen hatte, habe ich meinen Code (token.go) so gekapselt

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

Ich habe jedoch die folgende Fehlermeldung erhalten: "token.go: undefined: myLookupKey" Ich habe im Internet nachgesehen und eine gekapselte Funktion gefunden, die diesen Prototyp aufweist:

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

Was ist also der Unterschied zwischen meiner Funktion und dieser? Wie kann ich dieses verwenden?

Vielen Dank !

17
Emixam23

Um zu beginnen, müssen Sie eine JWT-Bibliothek in Golang importieren. Sie finden diese Bibliotheksdokumentation unter dem folgenden Link.

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

Zunächst müssen Sie ein Token erstellen

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

Zweitens parsen Sie dieses Zeichen

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

Es gibt auch einige Beispiele für die Verwendung von JWT in GOlang. 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.")
    }
}
22

Nur um ein Update von @ massoud-afrashteh zu machen ..__ In Version 3 von jwt-go sollten Muscheln gesetzt werden

// Set some claims claims := make(jwt.MapClaims) claims["foo"] = "bar" claims["exp"] = time.Now().Add(time.Hour * 72).Unix() token.Claims = claims

5
Paval

Vergessen Sie nicht, den Befehl go get github.com/dgrijalva/jwt-go auszuführen.

Ein anderer Weg, um einfacher zu erstellen:

token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
   "foo": "bar",
   "nbf": time.Date(2015, 10, 10, 12, 0, 0, 0, time.UTC).Unix(),
})
tokenString, err := token.SignedString([]byte("your key"))
fmt.Println(tokenString, err)
4
icaksama
func GenerateToken(mySigningKey []byte, username string) (string, error) {
    // Create the token
    token := jwt.New(jwt.SigningMethodRS512)
    claims := make(jwt.MapClaims)
    claims[collections.PARAM_USER_NAME] = username
    claims["exp"] = time.Now().Add(time.Hour * 72).Unix()
    token.Claims = claims
    return token.SignedString(mySigningKey)
}
1
Black_Dreams