2017-01-16 107 views
0

我是新开发web应用程序。我正在与golang合作,并希望安全地为用户上传的文件提供服务,例如只允许他们查看他们自己的文件。你如何在golang中安全地提供文件

现在我已经将这些文件保存到具有随机名称的本地文件系统。如果我服务整个目录,恶意用户可能会查看其他用户文件。这听起来像是一个常见用例,我想知道处理它的最佳方法是什么?

+0

只需在用户要求查看其文件之一的路线上添加验证层,而不是直接从网络服务器提供它们。 –

+0

你可以使用'http.ServeFile()'来提供一个文件。有些控制器逻辑当然是 –

回答

2

这个问题非常模糊,而且架构决策必须优化数据访问并保护文件。

但是,下面是一个简单的解决方案,可以用于您的用例。

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") 
    } 
} 

在这里,我用地图来存储文件的权限。我建议你改为使用SQL表。

+0

在这种情况下,你如何去掉前缀? – Apophis

0

如果你的文件名是随机的,足够长,并使用安全的随机生成器,这已经是安全的(除非目录列表已启用),但有一些限制。

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

一个用户将只能访问,如果他有与随机名称的URL文件。限制是,尽管URL将被保存在浏览器历史记录中,但如果其他人发现它也可以访问它。