Go и JWT - простая аутентификация

В настоящее время я делаю 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?

Спасибо за помощь !

ИЗМЕНИТЬ 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: undefined: myLookupKey». Я поискал в Интернете и нашел инкапсулированную функцию, которая имеет этот прототип:

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

Так в чем разница между моей функцией и этой? Как я могу использовать это?

Спасибо !


person Emixam23    schedule 26.03.2016    source источник
comment
Пример кода с использованием карты утверждений не работает. За это время API мог быть изменен.   -  person chmike    schedule 26.08.2017
comment
Честно говоря, понятия не имею: / Давным-давно, а сегодня сменил работу так ..: /   -  person Emixam23    schedule 27.08.2017
comment
Хранить пароль в утверждениях токена не рекомендуется, файл cookie токена не зашифрован, пользователь может его прочитать.   -  person Chris    schedule 29.05.2019


Ответы (3)


Для начала вам необходимо импортировать библиотеку JWT в Golang (перейдите по ссылке 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(":(")
}

Кроме того, есть несколько примеров использования JWT в GOlang, например: 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.")
    }
}
person coditori    schedule 26.03.2016
comment
После jwt-go это решение не работает. Пожалуйста, обновите ответ. - person Karlom; 06.07.2017

Просто чтобы обновить ответ @ massoud-afrashteh. В версии 3 jwt-go установка моллюсков должна быть

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

Не забудьте запустить команду go get github.com/dgrijalva/jwt-go.

Другой способ создать попроще:

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)
person icaksama    schedule 14.12.2018