如何在golang中安全地提供文件服务

huangapple go评论104阅读模式
英文:

How do you securely serve a file in golang

问题

我是新手开发者,正在使用golang开发Web应用程序。我想要安全地提供用户上传的文件,例如只允许他们查看自己的文件。

目前,我已将这些文件保存到本地文件系统中,并使用随机名称。如果我提供整个目录,恶意用户可能会查看其他用户的文件。这似乎是一个常见的使用情况,我想知道如何处理这个问题的最佳方法。

英文:

I'm new to developing web applications. I'm working with golang and would like to serve user uploaded files securely, such as allowing them to view their own files only.

Now I have saved those files to a local file system with random names. If I serve the entire directory, malicious users may view other users files. This sounds like a common use case, I wonder what's the best approach to deal with it?

答案1

得分: 3

这个问题相当模糊,需要做出架构决策来优化数据访问并保护文件的安全。

然而,这里有一个简单的解决方案可能适用于您的用例。

package main

import (
	"fmt"
	"mime"
	"net/http"
	"path/filepath"
)

// UserFilesMap是包含文件权限的映射
var UserFilesMap map[string]FilePermission

type FilePermission map[string]struct{}

// FileServer是用于提供文件的函数
func FileServer(w http.ResponseWriter, r *http.Request) {
	// 获取用户想要访问的文件路径
	filename := r.URL.Path[9:]
	var uname, pass string
	var ok bool
	if uname, pass, ok = r.BasicAuth(); !ok {
		w.WriteHeader(http.StatusForbidden)
		return
	}

	if !(uname == "user" && pass == "1234") {
		w.WriteHeader(http.StatusForbidden)
		return
	}

	// 检查用户是否有权限访问文件
	if _, ok := UserFilesMap[uname][filename]; !ok {
		w.WriteHeader(http.StatusForbidden)
		return
	}

	w.Header().Set("Content-Type", mime.TypeByExtension(filepath.Ext(filename)))
	http.ServeFile(w, r, "files/"+filename)
}

func main() {
	UserFilesMap = make(map[string]FilePermission)
	// UserFilesMap["user"] = FilePermission{"xyz.txt": struct{}{}}
	UserFilesMap["user"] = FilePermission{"abc.txt": struct{}{}}
	http.HandleFunc("/getFile/", FileServer)
	if err := http.ListenAndServe(":8080", nil); err != nil {
		fmt.Println("Error in ListenAndServe")
	}
}

在这里,我使用了一个映射来存储文件的权限。我建议您改为使用一个SQL表。

英文:

This question in pretty vague and architectural decisions must be made to optimize data access and secure the files.

However, here is a simple solution that might serve your use-case.

package main
import (
"fmt"
"mime"
"net/http"
"path/filepath"
)
//UserFilesMap is the map that contains
var UserFilesMap map[string]FilePermission
type FilePermission map[string]struct{}
//FileServer is the function that serves files
func FileServer(w http.ResponseWriter, r *http.Request) {
//get the file path the user wants to access
filename := r.URL.Path[9:]
var uname, pass string
var ok bool
if uname, pass, ok = r.BasicAuth(); !ok {
w.WriteHeader(http.StatusForbidden)
return
}
if !(uname == "user" && pass == "1234") {
w.WriteHeader(http.StatusForbidden)
return
}
//Checking if user has permission to the file
if _, ok := UserFilesMap[uname][filename]; !ok {
w.WriteHeader(http.StatusForbidden)
return
}
w.Header().Set("Content-Type", mime.TypeByExtension(filepath.Ext(filename)))
http.ServeFile(w, r, "files/"+filename)
}
func main() {
UserFilesMap = make(map[string]FilePermission)
// UserFilesMap["user"] = FilePermission{"xyz.txt": struct{}{}}
UserFilesMap["user"] = FilePermission{"abc.txt": struct{}{}}
http.HandleFunc("/getFile/", FileServer)
if err := http.ListenAndServe(":8080", nil); err != nil {
fmt.Println("Error in ListenAndServe")
}
}

Here, I used a map to store the permissions of files. I would suggest you go for a SQL table instead.

答案2

得分: 0

如果您的文件名足够随机且足够长,并且使用安全的随机生成器,那么这已经是安全的(除非启用了目录列表)。但是,仍然存在一些限制。

https://golang.org/pkg/crypto/rand/

只有拥有带有随机名称的URL的用户才能访问该文件。但是,限制在于URL将保存在浏览器历史记录中,如果其他人找到它,他们也将能够访问该文件。

英文:

If ur filenames are random and long enough and use a secure random generator this is already secure (unless directory-listing is enabled) with some limits though.

https://golang.org/pkg/crypto/rand/

One user will have access to the file only if he has the url with the random name. The limitation is though that the URL will be saved in the browser history, if someone else finds it he will also have access to it.

huangapple
  • 本文由 发表于 2017年1月17日 03:45:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/41683952.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定