Fiber JWT
Das JWT-Middleware gibt ein JSON Web Token (JWT)-Authentifizierungsmiddleware zurück. Für ein gültiges Token setzt es den Benutzer in Ctx.Locals und ruft den nächsten Handler auf. Bei einem ungültigen Token gibt es einen "401 - Nicht autorisiert" Fehler zurück. Bei einem fehlenden Token gibt es einen "400 - Schlechte Anfrage" Fehler zurück.
Hinweis: Go-Version 1.19 oder höher ist erforderlich
Installation
Diese Middleware unterstützt Fiber v1 und v2, bitte entsprechend installieren.
go get -u github.com/gofiber/fiber/v2
go get -u github.com/gofiber/contrib/jwt
go get -u github.com/golang-jwt/jwt/v5
Signatur
jwtware.New(config ...jwtware.Config) func(*fiber.Ctx) error
Konfiguration
Eigenschaft | Typ | Beschreibung | Standardwert |
---|---|---|---|
Filter | func(*fiber.Ctx) bool |
Definiert eine Funktion zum Überspringen der Middleware | nil |
SuccessHandler | func(*fiber.Ctx) error |
Definiert eine Funktion zum Ausführen bei gültigem Token | nil |
ErrorHandler | func(*fiber.Ctx, error) error |
Definiert eine Funktion zum Ausführen bei ungültigem Token | 401 Ungültiges oder abgelaufenes JWT |
SigningKey | interface{} |
Der Signaturschlüssel, der zur Überprüfung des Tokens verwendet wird. Wenn die Länge von SigningKeys 0 ist, wird er als Fallback verwendet | nil |
SigningKeys | map[string]interface{} |
Die Zuordnung von Signaturschlüsseln, die zur Überprüfung von Tokens mit einem kid -Feld verwendet werden |
nil |
ContextKey | string |
Der Kontextschlüssel, der zur Speicherung von Benutzerinformationen aus dem Token im Kontext verwendet wird | "user" |
Claims | jwt.Claim |
Die erweiterten Anspruchsdaten, die den Tokeninhalt definieren | jwt.MapClaims{} |
TokenLookup | string |
Ein String im Format : , der zum Parsen des Tokens verwendet wird |
"header:Authorization" |
AuthScheme | string |
Das in der Autorisierungs-Header verwendete AuthScheme. Der Standardwert ("Bearer") wird nur mit dem Standardwert TokenLookup verwendet |
"Bearer" |
KeyFunc | func() jwt.Keyfunc |
Eine benutzerdefinierte Funktion zur Bereitstellung eines öffentlichen Schlüssels für die Tokenüberprüfung | jwtKeyFunc |
JWKSetURLs | []string |
Eine Liste von eindeutigen JSON Web Key (JWK) Set URLs, die zum Parsen von JWT verwendet werden | nil |
Beispiel von HS256
package main
import (
"time"
"github.com/gofiber/fiber/v2"
jwtware "github.com/gofiber/contrib/jwt"
"github.com/golang-jwt/jwt/v5"
)
func main() {
app := fiber.New()
// Login-Route
app.Post("/login", login)
// Zugängliche Route ohne Authentifizierung
app.Get("/", accessible)
// JWT-Middleware
app.Use(jwtware.New(jwtware.Config{
SigningKey: jwtware.SigningKey{Key: []byte("secret")},
}))
// Eingeschränkte Route
app.Get("/restricted", restricted)
app.Listen(":3000")
}
func login(c *fiber.Ctx) error {
user := c.FormValue("user")
pass := c.FormValue("pass")
// Fehler bei Nichtautorisiertem
if user != "john" || pass != "doe" {
return c.SendStatus(fiber.StatusUnauthorized)
}
// Ansprüche erstellen
claims := jwt.MapClaims{
"name": "John Doe",
"admin": true,
"exp": time.Now().Add(time.Hour * 72).Unix(),
}
// Token erstellen
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
// Codierten Token generieren und als Antwort senden
t, err := token.SignedString([]byte("secret"))
if err != nil {
return c.SendStatus(fiber.StatusInternalServerError)
}
return c.JSON(fiber.Map{"token": t})
}
func accessible(c *fiber.Ctx) error {
return c.SendString("Zugänglich")
}
func restricted(c *fiber.Ctx) error {
user := c.Locals("user").(*jwt.Token)
claims := user.Claims.(jwt.MapClaims)
name := claims["name"].(string)
return c.SendString("Willkommen " + name)
}
HS256 Test
Melden Sie sich mit Benutzername und Passwort an, um ein Token zu erhalten.
curl --data "user=john&pass=doe" http://localhost:3000/login
Antwort
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0NjE5NTcxMzZ9.RB3arc4-OyzASAaUhC2W3ReWaXAt_z2Fd3BN4aWTgEY"
}
Anfrage für eingeschränkte Ressourcen unter Verwendung des Tokens im Autorisierungsheader.
curl localhost:3000/restricted -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0NjE5NTcxMzZ9.RB3arc4-OyzASAaUhC2W3ReWaXAt_z2Fd3BN4aWTgEY"
Antwort
Willkommen John Doe
package main
import (
"crypto/rand"
"crypto/rsa"
"log"
"time"
"github.com/gofiber/fiber/v2"
"github.com/golang-jwt/jwt/v5"
jwtware "github.com/gofiber/contrib/jwt"
)
var (
// Offensichtlich handelt es sich hier nur um ein Testbeispiel. Machen Sie dies nicht in der Produktion.
// In der Produktion sollten Sie das Schlüsselpaar im Voraus generieren.
// Fügen Sie niemals den privaten Schlüssel zu einem GitHub-Repository hinzu.
privateKey *rsa.PrivateKey
)
func main() {
app := fiber.New()
// Generieren Sie zum Zweck der Demonstration jedes Mal, wenn das Programm ausgeführt wird, ein neues privates/öffentliche Schlüsselpaar. Siehe die obige Anmerkung.
rng := rand.Reader
var err error
privateKey, err = rsa.GenerateKey(rng, 2048)
if err != nil {
log.Fatalf("rsa.GenerateKey:%v", err)
}
// Login-Route
app.Post("/login", login)
// Unauthentifizierte Route
app.Get("/", accessible)
// JWT-Middleware
app.Use(jwtware.New(jwtware.Config{
SigningKey: jwtware.SigningKey{
JWTAlg: jwtware.RS256,
Key: privateKey.Public(),
},
}))
// Eingeschränkte Route
app.Get("/restricted", restricted)
app.Listen(":3000")
}
func login(c *fiber.Ctx) error {
user := c.FormValue("user")
pass := c.FormValue("pass")
// Werfen Sie einen unbefugten Fehler
if user != "john" || pass != "doe" {
return c.SendStatus(fiber.StatusUnauthorized)
}
// Erstellen von Ansprüchen
claims := jwt.MapClaims{
"name": "John Doe",
"admin": true,
"exp": time.Now().Add(time.Hour * 72).Unix(),
}
// Erstellen des Tokens
token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
// Generieren des codierten Tokens und Senden als Antwort
t, err := token.SignedString(privateKey)
if err != nil {
log.Printf("token.SignedString:%v", err)
return c.SendStatus(fiber.StatusInternalServerError)
}
return c.JSON(fiber.Map{"token": t})
}
func accessible(c *fiber.Ctx) error {
return c.SendString("Erreichbar")
}
func restricted(c *fiber.Ctx) error {
user := c.Locals("user").(*jwt.Token)
claims := user.Claims.(jwt.MapClaims)
name := claims["name"].(string)
return c.SendString("Willkommen " + name)
}
RS256 Test
RS256 ist im Wesentlichen dasselbe wie der obige HS256-Test.
JWK-Set-Test
Diese Tests sind wie die grundlegenden JWT-Tests oben, erfordern jedoch gültige öffentliche Schlüsselsätze im JWK-Set-Format unter JWKSetURLs.
Beispiel für benutzerdefinierte KeyFunc
Die KeyFunc definiert eine benutzerdefinierte Funktion, die verwendet wird, um öffentliche Schlüssel für die Tokenvalidierung bereitzustellen. Diese Funktion ist dafür verantwortlich, den Signaturalgorithmus zu validieren und den richtigen Schlüssel auszuwählen. Wenn das Token von einer externen Partei ausgestellt wird, kann die benutzerdefinierte KeyFunc nützlich sein.
Wenn eine benutzerdefinierte KeyFunc bereitgestellt wird, werden SigningKey, SigningKeys und SigningMethod ignoriert. Dies ist eine von drei Optionen zur Bereitstellung von Tokenvalidierungsschlüsseln. Die Prioritätsreihenfolge ist die benutzerdefinierte KeyFunc, SigningKeys und SigningKey. Wenn weder SigningKeys noch SigningKey bereitgestellt werden, muss diese Funktion bereitgestellt werden. Standardmäßig wird der Signaturalgorithmus validiert und der geeignete Schlüssel mithilfe der internen Implementierung ausgewählt.
package main
import (
"fmt"
"github.com/gofiber/fiber/v2"
jwtware "github.com/gofiber/contrib/jwt"
"github.com/golang-jwt/jwt/v5"
)
func main() {
app := fiber.New()
app.Use(jwtware.New(jwtware.Config{
KeyFunc: customKeyFunc(),
}))
app.Get("/ok", func(c *fiber.Ctx) error {
return c.SendString("OK")
})
}
func customKeyFunc() jwt.Keyfunc {
return func(t *jwt.Token) (interface{}, error) {
// Überprüfen, ob die Signaturmethode korrekt ist
if t.Method.Alg() != jwtware.HS256 {
return nil, fmt.Errorf("Unerwartete jwt-Signaturmethode=%v", t.Header["alg"])
}
// TODO: Implementierung der benutzerdefinierten Ladung des Signaturschlüssels, z. B. Laden aus der Datenbank
signingKey := "geheim"
return []byte(signingKey), nil
}
}