Fiber JWT

JWT middleware, JSON Web Token (JWT) kimlik doğrulama ara yazılımını döndürür. Geçerli bir jeton için kullanıcıyı Ctx.Locals'e ayarlar ve sonraki işleyiciyi çağırır. Geçersiz bir jeton için "401 - Yetkisiz" hatası döndürür. Eksik bir jeton için "400 - Kötü İstek" hatası döndürür.

Not: Go sürüm 1.19 veya daha yükseği gerektirir

Kurulum

Bu ara yazılım, Fiber v1 ve v2'yi destekler, lütfen buna göre yükleyin.

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

İmza

jwtware.New(config ...jwtware.Config) func(*fiber.Ctx) error

Yapılandırma

Özellik Tür Açıklama Varsayılan Değer
Filtre func(*fiber.Ctx) bool Ara yazılımı atlamak için bir işlev tanımlar nil
Başarı İşleyici func(*fiber.Ctx) error Geçerli jetonla uygun işlevi tanımlar nil
Hata İşleyici func(*fiber.Ctx, error) error Geçersiz jetonla uygun işlevi tanımlar 401 Geçersiz veya süresi dolmuş JWT
İmza Anahtarı interface{} Jetonu doğrulamak için kullanılan imza anahtarı. SigningKeys'in uzunluğu 0 ise yedek olarak kullanılır nil
İmza Anahtarları map[string]interface{} kid alanıyla jetonları doğrulamak için kullanılan imza anahtarlarının eşlemesi nil
Context Anahtarı string Kullanıcı bilgisini içerikteki çalışma alanına depolamak için kullanılan bağlam anahtarı "kullanıcı"
Talepler jwt.Claim Jeton içeriğini tanımlayan genişletilmiş talepler veri yapısı jwt.MapClaims{}
Token Arayışı string : biçiminde kullanılan jetonu ayrıştırmak için bir dize "header:Authorization"
AuthScheme string Yetki başlığında kullanılan AuthScheme. Varsayılan değer ("Bearer") yalnızca varsayılan TokenLookup değeriyle kullanılır "Bearer"
KeyFunc func() jwt.Keyfunc Jeton doğrulaması için genel anahtarı sağlamak için kullanıcı tanımlı bir işlev jwtKeyFunc
JWKSetURLs []string JWT ayrıştırmak için kullanılan benzersiz JSON Web Key (JWK) Set URL'lerinin bir dilimi nil

HS256 Örneği

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

	// Giriş rotası
	app.Post("/login", login)

	// Kimlik doğrulama olmadan erişilebilir rotası
	app.Get("/", accessible)

	// JWT ara yazılımı
	app.Use(jwtware.New(jwtware.Config{
		SigningKey: jwtware.SigningKey{Key: []byte("secret")},
	}))

	// Kısıtlı rotası
	app.Get("/restricted", restricted)

	app.Listen(":3000")
}

func login(c *fiber.Ctx) error {
	user := c.FormValue("user")
	pass := c.FormValue("pass")

	// Yetkilendirilmemiş hata fırlatma
	if user != "john" || pass != "doe" {
		return c.SendStatus(fiber.StatusUnauthorized)
	}

	// Talepler oluşturma
	claims := jwt.MapClaims{
		"name":  "John Doe",
		"admin": true,
		"exp":   time.Now().Add(time.Hour * 72).Unix(),
	}

	// Jeton oluşturma
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)

	// Kodlanmış jeton oluşturma ve yanıt olarak gönderme
	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("Erişilebilir")
}

func restricted(c *fiber.Ctx) error {
	user := c.Locals("user").(*jwt.Token)
	claims := user.Claims.(jwt.MapClaims)
	name := claims["name"].(string)
	return c.SendString("Hoş geldin " + name)
}

HS256 Test

Username ve şifre ile giriş yaparak bir belirteç elde edin.

curl --data "user=john&pass=doe" http://localhost:3000/login

Cevap

{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0NjE5NTcxMzZ9.RB3arc4-OyzASAaUhC2W3ReWaXAt_z2Fd3BN4aWTgEY"
}

Yetkilendirme başlığında belirteceği kullanarak kısıtlanmış kaynağı isteyin.

curl localhost:3000/restricted -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0NjE5NTcxMzZ9.RB3arc4-OyzASAaUhC2W3ReWaXAt_z2Fd3BN4aWTgEY"

Cevap

Hoş geldiniz 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 (
	// Açıkçası, bu sadece bir test örneğidir. Üretim ortamında bunu yapmayın.
	// Üretimde, anahtar çiftini önceden oluşturmalısınız.
	// Özel anahtarı hiçbir GitHub deposuna eklemeyin.
	privateKey *rsa.PrivateKey
)

func main() {
	app := fiber.New()

	// Gösterim amaçlı, program her çalıştığında new private/public key pair'a oluşturun. Yukarıdaki notu görün.
	rng := rand.Reader
	var err error
	privateKey, err = rsa.GenerateKey(rng, 2048)
	if err != nil {
		log.Fatalf("rsa.GenerateKey:%v", err)
	}

	// Giriş rotası
	app.Post("/login", login)

	// Kimlik doğrulama olmayan rota
	app.Get("/", accessible)

	// JWT ara yazılım
	app.Use(jwtware.New(jwtware.Config{
		SigningKey: jwtware.SigningKey{
			JWTAlg: jwtware.RS256,
			Key:    privateKey.Public(),
		},
	}))

	// Kısıtlanmış rota
	app.Get("/restricted", restricted)

	app.Listen(":3000")
}

func login(c *fiber.Ctx) error {
	user := c.FormValue("user")
	pass := c.FormValue("pass")

	// Yetkisiz hata fırlat
	if user != "john" || pass != "doe" {
		return c.SendStatus(fiber.StatusUnauthorized)
	}

	// Talepleri oluştur
	claims := jwt.MapClaims{
		"name":  "John Doe",
		"admin": true,
		"exp":   time.Now().Add(time.Hour * 72).Unix(),
	}

	// Belirteç oluştur
	token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims)

	// Kodlanmış belirteç oluştur ve cevap olarak gönder
	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("Erişilebilir")
}

func restricted(c *fiber.Ctx) error {
	user := c.Locals("user").(*jwt.Token)
	claims := user.Claims.(jwt.MapClaims)
	name := claims["name"].(string)
	return c.SendString("Hoş geldiniz " + name)
}

RS256 Test

RS256, temelde yukarıdaki HS256 testiyle aynıdır.

JWK Set Test

Bu testler, temel JWT testleriyle aynıdır, ancak JWKSetURLs adresinde JWK Set biçiminde geçerli genel anahtar setleri gerektirmektedir.

Özel KeyFunc Örneği

KeyFunc, token doğrulaması için kullanılan genel anahtarları sağlamak için kullanıcı tanımlı bir işlevi tanımlar. Bu işlev, imza algoritmasını doğrulamak ve doğru anahtarı seçmekten sorumludur. Eğer token harici bir taraf tarafından verilmişse, kullanıcı tanımlı KeyFunc yararlı olabilir.

Kullanıcı tanımlı KeyFunc sağlandığında, SigningKey, SigningKeys ve SigningMethod yoksayılır. Bu, token doğrulama anahtarlarını sağlamanın üç seçeneğinden biridir. Öncelik sırası kullanıcı tanımlı KeyFunc, SigningKeys ve SigningKey'dir. Eğer ne SigningKeys ne de SigningKey sağlanmamışsa, bu işlev sağlanmalıdır. Varsayılan olarak, içsel uygulama kullanılarak imza algoritmasını doğrulamak ve uygun anahtarı seçmek için uygulanır.

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) {
		// İmza yönteminin doğru olup olmadığını kontrol et
		if t.Method.Alg() != jwtware.HS256 {
			return nil, fmt.Errorf("Beklenmeyen jwt imza yöntemi=%v", t.Header["alg"])
		}

		// İmza anahtarının özel yüklenmesini uygula, örn. veritabanından yükle
    signingKey := "gizli"

		return []byte(signingKey), nil
	}
}