1043 字
5 分钟
Go 语言笔记
2023-08-02

Fiber 使用 JWT 登录验证#

创建 项目#

mkdir go-fiber-jwt
cd go-fiber-jwt
go mod init go-fiber-jwt

安装相关依赖#

go get github.com/gofiber/fiber/v2
go get github.com/gofiber/contrib/jwt

编写 JWT 校验中间件#

// jwt.go
package main

import (
	jwtware "github.com/gofiber/contrib/jwt"
	"github.com/gofiber/fiber/v2"
)

// Protected jwt 校验中间件
func Protected() fiber.Handler {
	return jwtware.New(jwtware.Config{
		SigningKey:   jwtware.SigningKey{Key: []byte("JWT密钥")},
		ErrorHandler: jwtError,
	})
}

// jwt 校验错误处理器
func jwtError(c *fiber.Ctx, _ error) error {
	return c.Status(fiber.StatusUnauthorized).SendStren("缺少 JWT 或 JWT 格式错误")
}

编写登录处理器#

// login.go
package main

import (
	"fmt"
	"github.com/gofiber/fiber/v2"
	"github.com/golang-jwt/jwt/v5"
	"time"
)

// LoginRequest 登录请求
type LoginRequest struct {
	Username string `json:"username"`
	Password string `json:"password"`
}

// Login 登录获取 token
func Login(ctx *fiber.Ctx) error {
	var err error
	loginRequest := LoginRequest{}
	// 获取登录请求体
	err = ctx.BodyParser(&loginRequest)
	if err != nil {
		return err
	}

	// TODO 检查用户名密码

	// 生成 token 返回
 	jwts := jwt.New(jwt.SigningMethodHS256)
	claims := jwts.Claims.(jwt.MapClaims)
	claims["username"] = loginRequest.Username
	// 过期时间
	claims["exp"] = time.Now().Add(time.Hour * 24).Unix()
	token, err := jwts.SignedString([]byte("JWT密钥"))
	if err != nil {
		return err
	}
	return ctx.SendString(token)
}

注册中间件和处理器#

// main.go
package main

import (
	"github.com/gofiber/fiber/v2"
	"log"
	"time"
)

func main() {
	app := fiber.New()
	// 设置路由
	app.Get("/login", Login)
	// 需要保护的路由添加中间件即可
	app.Get("/hello", Protected(), func(ctx *fiber.Ctx) error {
		return ctx.SendString("hello")
	})
	// 启动
	log.Fatal(app.Listen(":8080"))
}

操作 Minio#

Minio 官方提供了 Go 的 SDK,可以使用下列指令安装:

go get github.com/minio/minio-go/v7

并且提供了对应的文档:https://min.io/docs/minio/linux/developers/go/API.html

Go SDK 基本使用#

初始化上下文和客户端:

package main

import (
	"context"
	"log"

	"github.com/minio/minio-go/v7"
	"github.com/minio/minio-go/v7/pkg/credentials"
)

func main() {
	// 创建一个上下文,用于超时和取消等操作的处理,这里直接使用默认的实现
	ctx := context.Background()
	// 创建 minio 客户端
	endpoint := "127.0.1:9000"
	id := "admin"
	secret := "adminadmin"
	SessionToken := ""
	minioClient, err := minio.New(endpoint, &minio.Options{
		Creds: credentials.NewStaticV4(id, secret, SessionToken),
	})
	if err != nil {
		log.Fatalln(err)
	}
	// ...
}

上传文件:

func main() {
	// ...
	// 上传本地文件
	bucketName := "test"
	objectName := "123.jpg"
	filePath := "test.jpg"
	info, err := minioClient.FPutObject(ctx, bucketName, objectName, filePath, minio.PutObjectOptions{})
	if err != nil {
		log.Fatalln(err)
	}
	// 输出上传文件信息
	log.Printf("上传完成\n%#v", info)
}

下载文件:

func main() {
	// ...
	// 下载文件到本地
	bucketName := "test"
	objectName := "123.jpg"
	filePath := "456.jpg"
	err = minioClient.FGetObject(ctx, bucketName, objectName, filePath, minio.GetObjectOptions{})
	if err != nil {
		log.Fatalln(err)
	}
}

删除文件:

func main() {
	// ...
	// 删除文件
	bucketName := "test"
	objectName := "123.jpg"
	err = minioClient.RemoveObject(ctx, bucketName, objectName, minio.RemoveObjectOptions{})
}

使用 Gin 框架进行服务器文件上传和下载#

安装 Gin 框架:

go get github.com/gin-gonic/gin

完整代码:

package main

import (
	"context"
	"github.com/gin-gonic/gin"
	"log"
	"net/http"

	"github.com/minio/minio-go/v7"
	"github.com/minio/minio-go/v7/pkg/credentials"
)

func main() {
	// 创建一个上下文,用于超时和取消等操作的处理,这里直接使用默认的实现
	ctx := context.Background()
	// 创建 minio 客户端
	endpoint := "127.0.1:9000"
	id := "admin"
	secret := "adminadmin"
	SessionToken := ""
	bucketName := "test"
	minioClient, err := minio.New(endpoint, &minio.Options{
		Creds: credentials.NewStaticV4(id, secret, SessionToken),
	})
	if err != nil {
		log.Fatalln(err)
	}
	// 创建 gin 路由
	router := gin.Default()
	// 文件上传
	router.POST("/upload", func(c *gin.Context) {
		// 读取文件
		file, _ := c.FormFile("file")
		reader, _ := file.Open()
		defer func() {
			// 关闭流
			_ = reader.Close()
		}()
		// 上传到 minio
		object, _ := minioClient.PutObject(ctx, bucketName, file.Filename, reader, file.Size, minio.PutObjectOptions{})
		// 返回上传文件的信息
		c.JSON(http.StatusOK, object)
	})
	// 文件下载
	router.GET("/file/:name", func(c *gin.Context) {
		name := c.Param("name")
		// 读取文件
		object, _ := minioClient.GetObject(ctx, bucketName, name, minio.GetObjectOptions{})
		defer func() {
			// 关闭流
			_ = object.Close()
		}()
		// 返回文件
		c.DataFromReader(http.StatusOK, -1, "application/stream", object, nil)
	})
	// 监听 8080
	_ = router.Run(":8080")
}

使用 Fiber 框架进行服务器文件上传和下载#

安装 Fiber 框架:

go get github.com/gofiber/fiber/v2

完整代码:

package main

import (
	"context"
	"github.com/gofiber/fiber/v2"
	"github.com/gofiber/fiber/v2/utils"
	"github.com/minio/minio-go/v7"
	"github.com/minio/minio-go/v7/pkg/credentials"
	"log"
)

func main() {
	// 创建一个上下文,用于超时和取消等操作的处理,这里直接使用默认的实现
	ctx := context.Background()
	// 创建 minio 客户端
	endpoint := "127.0.1:9000"
	id := "admin"
	secret := "adminadmin"
	SessionToken := ""
	bucketName := "test"
	minioClient, err := minio.New(endpoint, &minio.Options{
		Creds: credentials.NewStaticV4(id, secret, SessionToken),
	})
	if err != nil {
		log.Fatalln(err)
	}
	// 创建 fiber 路由
	app := fiber.New()
	// 文件上传
	app.Post("/upload", func(c *fiber.Ctx) error {
		// 读取文件
		file, err := c.FormFile("file")
		if err != nil {
			return err
		}
		reader, err := file.Open()
		if err != nil {
			return err
		}
		defer func() {
			// 关闭流
			_ = reader.Close()
		}()
		// 上传到 minio
		filename := utils.UUID()
		contentType := file.Header["Content-Type"][0]
		object, err := minioClient.PutObject(ctx, bucketName, filename, reader, file.Size, minio.PutObjectOptions{
			ContentType: contentType,
		})
		if err != nil {
			return err
		}
		// 返回上传文件的信息
		return c.JSON(object)
	})
	// 文件下载
	app.Get("/file/:name", func(c *fiber.Ctx) error {
		name := c.Params("name", "")
		// 读取文件
		object, err := minioClient.GetObject(ctx, bucketName, name, minio.GetObjectOptions{})
		if err != nil {
			return err
		}
		// 返回文件
		return c.SendStream(object)
	})
	// 监听 8080
	log.Fatal(app.Listen(":8080"))
}
Go 语言笔记
https://flapypan.netlify.app/posts/go/
作者
FlapyPan
发布于
2023-08-02
许可协议
CC BY-NC-SA 4.0