ก่อนอื่นเราจะ Design Routing ก่อน ด้วย Rest Client ใน VSCode
@hostname = localhost@port = 8181@host = {{hostname}}:{{port}}@contentType = application/json###GET http://{{host}}/Content-Type: {{contentType}}###POST http://{{host}}/loginContent-Type: {{contentType}}{"username":"aofiee","password":"password"}###GET http://{{host}}/profileAuthorization: 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 typestype (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 routesimport ("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.LoginMsgToken types.Token)func Auth(c *fiber.Ctx) error {var l MsgLoginerr := 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 MsgTokentoken := 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 = trefreshToken := 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 = rtreturn msgToken, nil}//https://github.com/gofiber/jwtfunc 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 mainimport ("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 AuthorizationRequiredapp.Get("/", func(c *fiber.Ctx) error {return c.SendString("Hello, World!")})app.Post("/login", routes.Auth)//AuthorizationRequired Actionapp.Use(routes.AuthorizationRequired())//need AuthorizationRequiredapp.Get("/profile", routes.Profile)//end AuthorizationRequirederr := app.Listen(":" + os.Getenv("APP_PORT"))if err != nil {panic(err)}}
หลังจากนั้นเราใช้ Rest Client ยิงดู จะได้ผลตามรูป
Quick Links
Legal Stuff