GoFiber 从零系列(三):JWT注册,登录

2,000 阅读1分钟

GitHub项目地址

GoFiber 从零系列(一):项目创建&配置文件&gorm-mysql

GoFiber 从零系列(二):热加载/热更新 && 日志系统 && 验证入参

GoFiber 从零系列(三):JWT注册,登录

GoFiber 从零系列(五):腾讯云SMS && goredis && 简单的短信登录功能

安装插件

go get -u github.com/gofiber/jwt/v3
go get -u github.com/golang-jwt/jwt/v4

新建controllers/login.go

package controller

import (
	"github.com/gofiber/fiber/v2"
	"github.com/jinpikaFE/go_fiber/models"
	"github.com/jinpikaFE/go_fiber/pkg/logging"
	"github.com/jinpikaFE/go_fiber/pkg/valodates"
)

// 添加test
func Login(c *fiber.Ctx) error {
	login := &models.Login{}
	code := 200
	message := "SUCCESS"

	if err := c.BodyParser(login); err != nil {
		code = 500
		message = "参数解析错误"
		logging.Error(err)
	}

	// 入参验证
	errors := valodates.ValidateStruct(*login)

	if errors != nil {
		return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
			"code":    code,
			"message": message,
			"data":    errors,
		})
	}

	res := models.GetToken(login)

	if res == "" {
		code = fiber.StatusUnauthorized
		message = "账户或者密码错误"
		return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
			"code":    code,
			"message": message,
			"data":    res,
		})
	}

	return c.Status(fiber.StatusOK).JSON(fiber.Map{
		"code":    code,
		"message": message,
		"data":    res,
	})
}

新建middleware/jwt/jwt.go

package jwt

import (
	// "strings"
	// "time"

	"github.com/gofiber/fiber/v2"
	"github.com/jinpikaFE/go_fiber/pkg/logging"

	"github.com/golang-jwt/jwt/v4"
)

func Jwt(ctx *fiber.Ctx) error {
	// gofiber不需要去请求头中寻找Authorization: Bearer
	// 直接通过
	// user := c.Locals("user").(*jwt.Token)
	// claims := user.Claims.(jwt.MapClaims)
	user := ctx.Locals("user").(*jwt.Token)
	claims := user.Claims.(jwt.MapClaims)

	logging.Info(claims)
	return ctx.Next()
}

新建models/login.go

package models

import (
	"time"

	"github.com/golang-jwt/jwt/v4"
	"github.com/jinpikaFE/go_fiber/pkg/logging"
)

type Login struct {
	Username string `validate:"required" query:"username" json:"username" xml:"username" form:"username"`
	Password string `validate:"required" query:"password" json:"password" xml:"password" form:"password"`
}

func GetToken(login *Login) string {
	if login.Username != "admin" || login.Password != "admin" {
		return ""
	}

	claims := jwt.MapClaims{
		"username": login.Username,
		"admin":    true,
		"exp":      time.Now().Add(time.Hour * 72).Unix(),
	}

	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)

	t, err := token.SignedString([]byte("secret"))
	if err != nil {
		logging.Error(err)
		return ""
	}

	return t
}

新建 pkg/untils/jwt.go

package untils

import "github.com/gofiber/fiber/v2"

func JwtError(c *fiber.Ctx, err error) error {
	if err.Error() == "Missing or malformed JWT" {
		return c.Status(fiber.StatusBadRequest).
			JSON(fiber.Map{"code": fiber.StatusBadRequest, "message": "Missing or malformed JWT", "data": nil})
	}
	return c.Status(fiber.StatusUnauthorized).
		JSON(fiber.Map{"code": fiber.StatusUnauthorized, "message": "Invalid or expired JWT", "data": nil})
}

修改router.go

package routers

import (
	"github.com/gofiber/fiber/v2"
	"github.com/gofiber/fiber/v2/middleware/logger"
	"github.com/gofiber/fiber/v2/middleware/requestid"
	jwtware "github.com/gofiber/jwt/v3"
	controller "github.com/jinpikaFE/go_fiber/controllers"
	"github.com/jinpikaFE/go_fiber/middleware/jwt"
	"github.com/jinpikaFE/go_fiber/pkg/logging"
	"github.com/jinpikaFE/go_fiber/pkg/setting"
	"github.com/jinpikaFE/go_fiber/pkg/untils"
)

func InitRouter() *fiber.App {
	app := fiber.New(fiber.Config{
		ReadTimeout:  setting.ReadTimeout,
		WriteTimeout: setting.WriteTimeout,
	})

	app.Use(requestid.New())
	app.Use(logger.New(logger.Config{
		Format: "[INFO-${locals:requestid}]${time} pid: ${pid} status:${status} - ${method} path: ${path} queryParams: ${queryParams} body: ${body}\n resBody: ${resBody}\n error: ${error}\n",
		Output: logging.F,
	}))

	apiv1 := app.Group("/v1")

	{
		apiv1.Post("/login", controller.Login)
	}

	// JWT Middleware
	app.Use(jwtware.New(jwtware.Config{
		SigningKey: []byte("secret"),
		ErrorHandler: untils.JwtError,
	}))

	apiv1.Use(jwt.Jwt)

	{
		apiv1.Get("/test", controller.GetTests)
		apiv1.Post("/test", controller.AddTest)
		apiv1.Put("/test/:id", controller.EditTest)
		apiv1.Delete("/test/:id", controller.DelTest)
	}

	return app
}

image.png

image.png