http.FileServer 默认不安全,因不校验路径、不限制../遍历、无鉴权且未绑定IP,易导致敏感文件泄露;必须配合StripPrefix、绝对路径根目录、filepath.Clean及前缀校验使用。

直接用 http.FileServer 能跑起来,但不加防护就暴露在局域网里,等于把整个目录树交给任何人翻——这不是共享,是裸奔。
为什么 http.FileServer 默认不能直接用
它本身不做路径校验、不拦 ../、不鉴权、不绑定 IP,请求 /../../etc/passwd 可能真能读出来(取决于你传给 http.Dir 的路径是否可控)。常见错误现象:服务一开,别人连上就能看到你桌面所有文件,甚至触发杀毒软件告警。
-
http.Dir("./")是最危险写法,当前目录可能包含go.mod、.git等敏感路径 - 没用
http.StripPrefix就直接挂到"/",会导致 URL 路径和文件系统路径完全对齐,放大遍历风险 - Windows 下若用
"\data"这种反斜杠路径,filepath.Clean行为可能和预期不一致
安全启动:限定根目录 + 清洗路径
必须显式指定一个干净的共享根目录,并确保所有请求路径都落在这个范围内。关键不是靠 StripPrefix 挡,而是靠绝对路径前缀比对来防越界。
- 用
filepath.Abs("/path/to/share")得到真实绝对路径,避免相对路径歧义 - 对每个请求路径,先
filepath.Clean,再拼到根目录,最后用strings.HasPrefix(cleanedAbsPath, allowedRoot)校验 - 拒绝任何
clean后含".."或开头不是"/"的路径(防绕过) - 示例片段:
root := "/home/user/share"<br>absRoot, _ := filepath.Abs(root)<br>fs := http.FileServer(http.Dir(root))<br>http.Handle("/share/", http.StripPrefix("/share/", fs))
局域网可用:绑定内网 IP + 自动开浏览器
默认 http.ListenAndServe(":8080", nil) 监听 localhost,局域网设备根本连不上;而硬写 "0.0.0.0:8080" 又可能被外网扫到。稳妥做法是只绑内网 IP,再自动拉起浏览器。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
立即学习“go语言免费学习笔记(深入)”;
- 获取内网 IPv4 地址时,过滤掉
127.0.0.1和非To4()地址,取第一个有效项即可 - 启动服务用
http.ListenAndServe("192.168.1.100:8080", nil)(替换为你的真实内网 IP),别用":8080" - Windows 用
exec.Command("cmd", "/C", "start", url),macOS/Linux 用exec.Command("open", url)或exec.Command("xdg-open", url) - 延迟 2 秒再开浏览器,避免服务还没 ready 就跳转失败
基础权限:IP 白名单 + Basic Auth 两道关卡
局域网场景下,JWT 太重,Basic Auth 加 IP 白名单足够且可控。重点是别让认证头被中间设备吞掉,也别让浏览器无限弹窗。
- 从
r.RemoteAddr提纯 IP:用strings.Split(r.RemoteAddr, ":")[0],否则"192.168.1.5:54321"匹配不上白名单 -
Basic Auth用户名密码建议从环境变量读(os.Getenv("SHARE_USER")),避免硬编码进二进制 - 认证失败时返回
401并带WWW-Authenticate: Basic realm="share"头,否则浏览器不弹框 - 权限中间件里,校验通过后务必调用
http.ServeContent而非io.Copy,否则断点续传失效
真正麻烦的从来不是写几行 http.FileServer,而是让每一条路径请求都过三道筛:是不是在允许目录里、有没有合法认证、是不是来自可信 IP——少一道,就可能从“分享”变成“泄露”。

















