前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Golang 使用 Gin 框架实现上传功能同时避免木马图片攻击

Golang 使用 Gin 框架实现上传功能同时避免木马图片攻击

原创
作者头像
liuzhen007
发布2024-05-12 13:23:44
1230
发布2024-05-12 13:23:44
举报
文章被收录于专栏:流媒体音视频流媒体音视频

目录

前言

正文

结尾

前言

利用 Gin 框架,我们可以非常简单的实现上传服务接口的开发,今天我们就来看看 Gin 在这方面都支持哪些能力,能够为我们减少多少任务量。同时,本文还要演示如何限制木马病毒上传,这里以图片格式为例进行演示。

正文

当设计开发一个存储服务的时候,首先就要想到如何实现上传存储功能,Gin 框架能够非常简单的支持单文件上传和多文件同时上传,接下来通过实例分别介绍这两方面的内容。

一、单文件上传

首先,我们来看 Gin 框架如何实现单文件上传,一般上传文件格式会被定义成 multipart forms 类型,并且保存在 file 字段中。在服务器端处理上传数据时,可以通过 FormFile() 方法来解析 file 参数。具体编码请看下面的代码实例:

代码语言:javascript
复制
package main 

import "github.com/gin-gonic/gin"

func main() {
	router := gin.Default()
	// 为 multipart forms 类型设置一个较低的内存缓存 (默认是 32 MiB)
	router.MaxMultipartMemory = 8 << 20  // 8 MiB
	router.POST("/upload", func(c *gin.Context) {
		// 单文件
		file, _ := c.FormFile("file")
		log.Println(file.Filename)

		// 保存上传文件到目标目录
                dst := "/Users/lz/go/src/storage/bin/test/dst/dst.jpg"
		c.SaveUploadedFile(file, dst)

		c.String(http.StatusOK, fmt.Sprintf("'%s' uploaded!", file.Filename))
	})
	router.Run(":8080")
}

当我们在服务端使用 FormFile() 方法解析 file 字段时,返回的 file 对象是一个 multipart.FileHeader 指针类型,其中包含了源文件数据的地址,然后使用 SaveUploadedFile() 方法保存 file 对象,参数 dst 是目标文件地址。

代码非常简单,接下来让我测试一下服务是否好用,我们 curl 工具模拟上传行为,具体命令如下:

代码语言:javascript
复制
 curl -X POST http://localhost:8080/upload \
  -F "file=@/Users/lz/go/src/storage/bin/test/src/cover.jpg" \
  -H "Content-Type: multipart/form-data"

结果:在目标目录中找到了上传的 cover.jpg 文件,如下图所示:

二、多文件上传

Gin 框架不仅可以非常简单的支持单文件上传,还可以支持多文件同时上传,上传文件格式也会被定义成 multipart forms 类型,并且保存在 upload[] 字段中。在服务器端处理上传数据时,可以通过 File() 方法来解析 upload[] 参数。具体编码请看下面的代码实例:

代码语言:javascript
复制
func main() {
	router := gin.Default()
	// 限定 multipart forms 内容占用大小
	router.MaxMultipartMemory = 8 << 20  // 8 MiB
	router.POST("/upload", func(c *gin.Context) {
		// 多个 form 类型文件
		form, _ := c.MultipartForm()
		files := form.File["upload[]"]

		for _, file := range files {
			log.Println(file.Filename)

			// 保存到指定文件
            dst := "/Users/lz/go/src/storage/bin/test/dst/" + file.Filename
			c.SaveUploadedFile(file, dst)
		}
		c.String(http.StatusOK, fmt.Sprintf("%d files uploaded!", len(files)))
	})
	router.Run(":8080")
}

原理上类似,只是在服务器端对同时上传到多个文件分别进行了保存而已。

下面让我们同时上传两个文件测试一下服务是否好用,具体命令如下:

代码语言:javascript
复制
curl -X POST http://localhost:8080/upload \
  -F "upload[]=@/Users/lz/go/src/storage/bin/test/src/cover.jpg" \
  -F "upload[]=@/Users/lz/go/src/storage/bin/test/src/cover2.jpg" \
  -H "Content-Type: multipart/form-data"

结果也是正确的。

三、拦截木马图片

现在上传功能已经实现了,但是面临一个安全问题,就是不能什么类型的文件都可以上传,比如木马病毒文件,特别是被隐藏为图片格式的木马文件。看似是一个图片后缀的文件,其实是一个木马脚本。比如图片文件:muma.jpeg,我们使用 UE 编辑器打开这个文件,文件内容如下图所示:

然而,一个正常的 jpeg 图片文件的内容如下图所示:

那么,如何解决这个问题呢?毫无疑问,我们要做的就是区分正真的图片和木马图片。经过我一顿猛如虎的调研,终于找到了解决办法,那就利用 Golang 语言的标准库 —— image。

但是,有一个问题,image 库并没有支持所有图片类型的校验,目前仅支持 jpeg、gif、png 三种图片格式。我们封装一个方法,同时支持三种图片格式的真实性校验。

参考代码如下:

代码语言:javascript
复制
func CheckImageFile(path, style string) (string, error) {
	f, err := os.Open(path)
	if err != nil {
		fmt.Errorf("打开文件失败 %s", err.Error())
	}
	switch strings.ToUpper(style) {
	case "JPG", "JPEG":
		_, err = jpeg.Decode(f)
	case "PNG":
		_, err = png.Decode(f)
	case "GIF":
		_, err = gif.Decode(f)
	}
	if err != nil {
		fmt.Errorf("校验文件类型失败 %s", err.Error())
		return "", err
	}
	return "", nil
}

调用上述方法时,只需要传入图片路径和后缀类型,就可以校验文件的真实性。非常方便,本人已经验证通过。

结尾

通过文本的介绍,我们可以了解到 Gin 框架能够非常简单的支持单文件上传和多文件同时上传。

作者简介:大家好,我是 liuzhen007(Data-Mining),是一位音视频技术爱好者,同时也是CSDN博客专家、华为云社区云享专家、签约作者,欢迎关注我分享更多音视频相关内容!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 正文
    • 一、单文件上传
      • 二、多文件上传
        • 三、拦截木马图片
        • 结尾
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档