英文:
prevent access to files in folder with a golang server
问题
我有一个使用golang编写的服务器,处理文件夹路径的方式如下:
fs := http.FileServer(http.Dir("./assets"))
http.Handle("/Images/", fs)
http.ListenAndServe(":8000", nil)
但是在这个文件夹中有私有图片,不应该允许访问这些文件。那么我该如何保护图片的访问,并防止任何人访问文件夹中的内容呢?
例如,像这样:
英文:
I've a server in golang who handle folder path like that :
fs := http.FileServer(http.Dir("./assets"))
http.Handle("/Images/", fs)
http.ListenAndServe(":8000", nil)
But in this folder there are privates images, and it shouldn't be possible to access files. So how can i secure image access and prevent anybody to access content of folder.
like that for example :
答案1
得分: 2
如果你想使用http
包来阻止一个目录,也许这个代码对你有用:
package main
import (
"net/http"
"os"
)
type justFilesFilesystem struct {
fs http.FileSystem
}
func (fs justFilesFilesystem) Open(name string) (http.File, error) {
f, err := fs.fs.Open(name)
if err != nil {
return nil, err
}
return neuteredReaddirFile{f}, nil
}
type neuteredReaddirFile struct {
http.File
}
func (f neuteredReaddirFile) Readdir(count int) ([]os.FileInfo, error) {
return nil, nil
}
func main() {
fs := justFilesFilesystem{http.Dir("/tmp/")}
http.ListenAndServe(":8080", http.FileServer(fs))
}
这段代码可以用来阻止指定目录的访问。你可以将要阻止的目录路径替换为"/tmp/"
,然后运行该代码,它将在本地的8080端口上启动一个HTTP服务器,该服务器将只提供指定目录下的文件,而不会提供目录的列表。
英文:
If you want to block a directory using http
package, maybe this will be useful to you :
> https://groups.google.com/forum/#!topic/golang-nuts/bStLPdIVM6w
>
>
> package main
>
> import (
> "net/http"
> "os"
> )
>
> type justFilesFilesystem struct {
> fs http.FileSystem
> }
>
> func (fs justFilesFilesystem) Open(name string) (http.File, error) {
> f, err := fs.fs.Open(name)
> if err != nil {
> return nil, err
> }
> return neuteredReaddirFile{f}, nil
> }
>
> type neuteredReaddirFile struct {
> http.File
> }
>
> func (f neuteredReaddirFile) Readdir(count int) ([]os.FileInfo, error) {
> return nil, nil
> }
>
> func main() {
> fs := justFilesFilesystem{http.Dir("/tmp/")}
> http.ListenAndServe(":8080", http.FileServer(fs))
> }
答案2
得分: 1
一个简单的FileServer()包装器可以解决你的问题,现在你需要添加一些逻辑来进行授权。看起来你有唯一的名称,这很好,所以我为你创建了一个名称映射,现在你可以添加一些更动态的东西,比如一个键/存储(如memcached、redis等)。希望你能理解这些注释。
package main
import (
"log"
"net/http"
"strings"
)
// 在这里放置允许的哈希或键
// 你可以考虑将它们放在一个键/值存储中
//
var allowedImages = map[string]bool{
"key-abc.jpg": true,
"key-123.jpg": true,
}
func main() {
http.Handle("/Images/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// 在这里我们可以进行任何类型的检查,在这种情况下,我们将只是拆分URL并
// 检查图像名称是否在allowedImages映射中,我们可以在数据库或其他地方进行检查
//
parts := strings.Split(r.URL.Path, "/")
imgName := parts[len(parts)-1]
if _, contains := allowedImages[imgName]; !contains { // 如果映射包含图像名称
log.Printf("未找到图像:%q 路径:%s\n", imgName, r.URL.Path)
// 如果找不到图像,我们写入一个404
//
// 奖励:我们不列出目录,所以没有人能知道里面有什么 :)
//
http.NotFound(w, r)
return
}
log.Printf("提供允许的图像:%q\n", imgName)
fileServer := http.StripPrefix("/Images/", http.FileServer(http.Dir("./assets")))
fileServer.ServeHTTP(w, r) // StripPrefix()和FileServer()返回一个实现ServerHTTP()的处理程序
}))
http.ListenAndServe(":8000", nil)
}
你可以在这里查看代码:https://play.golang.org/p/ehrd_AWXim
英文:
A little wrapper over FileServer() solves your problem, now you have to add some sort of logic to do Authorization, it looks like you have unique names, that's good, so I just filter the image name for you creating a map of names, now you can add something more dynamic like a key/store(memcached, redis. etc.) Hope you can follow the comments
package main
import (
"log"
"net/http"
"strings"
)
// put the allowed hashs or keys here
// you may consider put them in a key/value store
//
var allowedImages = map[string]bool{
"key-abc.jpg": true,
"key-123.jpg": true,
}
func main() {
http.Handle("/Images/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// here we can do any kind of checking, in this case we'll just split the url and
// check if the image name is in the allowedImages map, we can check in a DB or something
//
parts := strings.Split(r.URL.Path, "/")
imgName := parts[len(parts)-1]
if _, contains := allowedImages[imgName]; !contains { // if the map contains the image name
log.Printf("Not found image: %q path: %s\n", imgName, r.URL.Path)
// if the image is not found we write a 404
//
// Bonus: we don't list the directory, so nobody can know what's inside :)
//
http.NotFound(w, r)
return
}
log.Printf("Serving allowed image: %q\n", imgName)
fileServer := http.StripPrefix("/Images/", http.FileServer(http.Dir("./assets")))
fileServer.ServeHTTP(w, r) // StripPrefix() and FileServer() return a Handler that implements ServerHTTP()
}))
http.ListenAndServe(":8000", nil)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论