HomeArtTechHackBlockchain

บันทึก การทำ Go fiber กับ JWT Middleware

By Khomkrid Lerdprasert
Published in Technology
June 05, 2021
1 min read
บันทึก การทำ Go fiber กับ JWT Middleware

จดบันทึกการ ใช้งาน JWT ร่วมกับ Go fiber สร้าง Middleware ตรวจสอบ login แบบง่ายๆ

ก่อนอื่นเราจะ Design Routing ก่อน ด้วย Rest Client ใน VSCode

@hostname = localhost
@port = 8181
@host = {{hostname}}:{{port}}
@contentType = application/json
###
GET http://{{host}}/
Content-Type: {{contentType}}
###
POST http://{{host}}/login
Content-Type: {{contentType}}
{
"username":"aofiee",
"password":"password"
}
###
GET http://{{host}}/profile
Authorization: Bearer xxxx

โดยเราจะทำงานต่อจาก บทความก่อน บันทึก การทำ Golang Live-reload ใน Docker Container เพราะงั้น เราจะทำงานใน โครงสร้าง Directory ประมาณนี้

microservices
├── Readme.http
├── go.mod
├── go.sum
├── main.bak
├── main.go
├── routes
│   └── LoginRoute.go
├── tmp
│   ├── build-errors.log
│   └── main
└── types
└── LoginType.go

LoginType.go เราจะใช้เก็บ struct ง่ายๆ

package types
type (
Login struct {
Username string `json:"username"`
Password string `json:"password"`
}
Token struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
}
)

LoginRoute.go เราจะเก็บ Routing ของการ Login, Auth

package routes
import (
"time"
"github.com/aofiee/diablos/types"
"github.com/form3tech-oss/jwt-go"
fiber "github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/utils"
jwtware "github.com/gofiber/jwt/v2"
)
const (
jwtSecret = "eiei"
)
type (
MsgLogin types.Login
MsgToken types.Token
)
func Auth(c *fiber.Ctx) error {
var l MsgLogin
err := c.BodyParser(&l)
if err != nil {
c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"error": "cannot parse json",
"msg": err.Error(),
})
return nil
}
if l.Username != "aofiee" || l.Password != "password" {
c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
"error": "Bad Credentials",
})
return nil
}
token, err := createToken()
if err != nil {
c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "StatusInternalServerError",
"msg": err.Error(),
})
return nil
}
c.Status(fiber.StatusOK).JSON(fiber.Map{
"access_token": token.AccessToken,
"refresh_token": token.RefreshToken,
"user": l.Username,
})
return nil
}
func createToken() (MsgToken, error) {
var msgToken MsgToken
token := jwt.New(jwt.SigningMethodHS256)
claims := token.Claims.(jwt.MapClaims)
claims["sub"] = utils.UUID()
claims["name"] = "Khomkrid Lerdprasert"
claims["exp"] = time.Now().Add(time.Minute * 15).Unix()
t, err := token.SignedString([]byte(jwtSecret))
if err != nil {
return msgToken, err
}
msgToken.AccessToken = t
refreshToken := jwt.New(jwt.SigningMethodHS256)
rtClaims := refreshToken.Claims.(jwt.MapClaims)
rtClaims["sub"] = utils.UUID()
rtClaims["exp"] = time.Now().Add(time.Hour * 24 * 7).Unix()
rt, err := token.SignedString([]byte(jwtSecret))
if err != nil {
return msgToken, err
}
msgToken.RefreshToken = rt
return msgToken, nil
}
//https://github.com/gofiber/jwt
func AuthorizationRequired() fiber.Handler {
return jwtware.New(jwtware.Config{
// Filter: nil,
SuccessHandler: AuthSuccess,
ErrorHandler: AuthError,
SigningKey: []byte(jwtSecret),
// SigningKeys: nil,
SigningMethod: "HS256",
// ContextKey: nil,
// Claims: nil,
// TokenLookup: nil,
// AuthScheme: nil,
})
}
func AuthError(c *fiber.Ctx, e error) error {
c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
"error": "Unauthorized",
"msg": e.Error(),
})
return nil
}
func AuthSuccess(c *fiber.Ctx) error {
c.Next()
return nil
}
func Profile(c *fiber.Ctx) error {
user := c.Locals("user").(*jwt.Token)
claims := user.Claims.(jwt.MapClaims)
sub := claims["sub"].(string)
c.Status(fiber.StatusOK).JSON(fiber.Map{
"sub": sub,
})
return nil
}

และ main.go

package main
import (
"os"
"github.com/aofiee/diablos/routes"
fiber "github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/logger"
"github.com/gofiber/fiber/v2/middleware/requestid"
"github.com/gofiber/fiber/v2/utils"
"github.com/joho/godotenv"
)
var (
app = fiber.New()
)
func init() {
err := godotenv.Load(".env")
if err != nil {
panic("Error loading .env file")
}
app.Use(requestid.New())
app.Use(requestid.New(requestid.Config{
Header: "Test-Service-Header",
Generator: func() string {
return utils.UUID()
},
}))
app.Use(logger.New(logger.Config{
Format: "${pid} ${status} - ${method} ${path}\n",
TimeFormat: "02-Jan-2006",
TimeZone: "Asia/Bangkok",
}))
}
func main() {
//not AuthorizationRequired
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Hello, World!")
})
app.Post("/login", routes.Auth)
//AuthorizationRequired Action
app.Use(routes.AuthorizationRequired())
//need AuthorizationRequired
app.Get("/profile", routes.Profile)
//end AuthorizationRequired
err := app.Listen(":" + os.Getenv("APP_PORT"))
if err != nil {
panic(err)
}
}

หลังจากนั้นเราใช้ Rest Client ยิงดู จะได้ผลตามรูป

Rest Client
Rest Client


Tags

#Go lang

Share

Previous Article
บันทึก การทำ Golang Live-reload ใน Docker Container
Khomkrid Lerdprasert

Khomkrid Lerdprasert

Full Stack Life

Related Posts

สร้าง Key pair เพื่อทำการ signing document signature ด้วย Go lang
March 13, 2024
1 min
© 2024, All Rights Reserved.
Powered By

Quick Links

Author

Social Media