JWT는 JSON Web Token(JWT) 인증 미들웨어를 반환합니다. 유효한 토큰의 경우 Ctx.Locals에 사용자를 설정하고 다음 핸들러를 호출합니다. 유효하지 않은 토큰의 경우 "401 - Unauthorized" 오류를 반환합니다. 토큰이 누락된 경우 "400 - Bad Request" 오류를 반환합니다.
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 (
// 분명히 이는 단순한 테스트 예제일 뿐입니다. 프로덕션에서는 이렇게 하지 마세요.
// 프로덕션에서는 사전에 생성된 비공개 키와 공개 키 쌍을 가지고 있어야 합니다.
// 절대 GitHub 저장소에 비공개 키를 추가하지 마세요.
privateKey *rsa.PrivateKey
)
func main() {
app := fiber.New()
// 데모용으로만 각 실행마다 새 개인 키/공개 키 쌍을 생성합니다. 위 주석을 참조하세요.
rng := rand.Reader
var err error
privateKey, err = rsa.GenerateKey(rng, 2048)
if err != nil {
log.Fatalf("rsa.GenerateKey: %v", err)
}
// 로그인 라우트
app.Post("/login", login)
// 인증되지 않은 라우트
app.Get("/", accessible)
// JWT 미들웨어
app.Use(jwtware.New(jwtware.Config{
SigningKey: jwtware.SigningKey{
JWTAlg: jwtware.RS256,
Key: privateKey.Public(),
},
}))
// 제한된 라우트
app.Get("/restricted", restricted)
app.Listen(":3000")
}
func login(c *fiber.Ctx) error {
user := c.FormValue("user")
pass := c.FormValue("pass")
// 인증되지 않은 오류 발생
if user != "john" || pass != "doe" {
return c.SendStatus(fiber.StatusUnauthorized)
}
// 클레임 생성
claims := jwt.MapClaims{
"name": "John Doe",
"admin": true,
"exp": time.Now().Add(time.Hour * 72).Unix(),
}
// 토큰 생성
token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
// 인코딩된 토큰 생성 및 응답으로 전송
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("Accessible")
}
func restricted(c *fiber.Ctx) error {
user := c.Locals("user").(*jwt.Token)
claims := user.Claims.(jwt.MapClaims)
name := claims["name"].(string)
return c.SendString("Welcome " + name)
}
RS256 테스트
RS256은 실제로 위의 HS256 테스트와 동일합니다.
JWK 세트 테스트
테스트는 위의 기본 JWT 테스트와 동일하지만, RFC 7517에 명시된 JSON Web Key(JWK) 세트 형식의 유효한 공개 키 컬렉션에 대한 JWKSetURLs를 제공해야 한다는 점이 다릅니다.
사용자 정의 KeyFunc 예제
KeyFunc는 토큰 검증을 위한 공개 키를 제공하는 사용자 정의 함수를 정의합니다. 이 함수는 서명 알고리즘을 검증하고 적절한 키를 선택하는 작업을 수행해야 합니다. 사용자 정의 KeyFunc는 토큰이 외부 당사자에 의해 발행된 경우 유용할 수 있습니다.
사용자 정의 KeyFunc가 제공되면 SigningKey, SigningKeys 및 SigningMethod는 무시됩니다. 이는 토큰 검증 키를 제공하는 세 가지 옵션 중 하나입니다.
우선 순위는 사용자 정의 KeyFunc, SigningKeys 및 SigningKey 순입니다. SigningKeys와 SigningKey가 모두 제공되지 않은 경우 필요합니다. 서명 알고리즘을 검증하고 적절한 키를 선택하는 내부 구현으로 기본 설정됩니다.
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) {
// 항상 서명 방법을 확인하세요
if t.Method.Alg() != jwtware.HS256 {
return nil, fmt.Errorf("Unexpected jwt signing method=%v", t.Header["alg"])
}
// TODO 데이터베이스 등에서 서명 키를 로드하는 사용자 정의 구현
signingKey := "secret"
return []byte(signingKey), nil
}
}