英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论