http.fileserver 默认无权限控制,需自定义handler实现ip白名单、basic auth、路径遍历防护及显式绑定局域网ip。

用 http.FileServer 搭共享服务,但默认没权限控制
Go 标准库的 http.FileServer 能快速起一个静态文件服务器,但它对所有请求一视同仁——只要路径合法,谁都能下载。局域网内直接暴露 http.FileServer 等于把文件夹“门都不关”地摆在路上。它不校验用户、不区分角色、也不拦非法路径遍历(比如 ../etc/passwd),必须自己包一层。
实操建议:
- 永远别直接
http.Handle("/", http.FileServer(...)),先套个中间件 - 用
http.StripPrefix配合自定义http.Handler,把路径解析、权限判断、文件读取三步拆开 - 禁用目录列表:在
http.FileServer前加拦截,对结尾是/的 GET 请求返回 403,避免泄露结构
用 net/http 中间件做基础权限校验
局域网场景下,IP 白名单 + Basic Auth 是最轻量、够用的组合。不需要 JWT 或 OAuth 这类重方案,反而容易出配置错或依赖漏洞。
常见错误现象:401 Unauthorized 返回了但浏览器反复弹窗、或者认证头被代理/路由器吞掉。
立即学习“go语言免费学习笔记(深入)”;
实操建议:
- Basic Auth 用户名密码硬编码进代码前,确认运行环境无源码泄露风险;更安全的做法是读
os.Getenv("SHARE_USER") - IP 白名单用
strings.HasPrefix(r.RemoteAddr, "192.168.1.")不可靠——r.RemoteAddr可能带端口(如192.168.1.100:54321),要用strings.Split(r.RemoteAddr, ":")[0]提纯 - 务必在权限校验后调用
http.ServeContent而非直接io.Copy,否则不支持断点续传和If-Modified-Since
防止路径遍历:别信 filepath.Clean 单独干活
filepath.Clean("../secret.txt") 确实会变成 secret.txt,但这是在服务端路径上下文里 clean 的——如果原始请求是 GET /share/../../etc/shadow,而你的根目录设的是 /var/www,clean 后拼出来可能是 /var/www/../etc/shadow,仍可能越界。
使用场景:用户通过 URL 路径访问子目录,比如 /share/docs/report.pdf,你得确保他只能在 /share 对应的真实目录下翻。
实操建议:
- 把允许访问的根路径转成绝对路径(
filepath.Abs("/path/to/share")),再对请求路径 clean 后拼接,最后用strings.HasPrefix(cleanedAbsPath, allowedRoot)做前缀校验 - Windows 下注意路径分隔符差异,统一用
filepath.ToSlash转成正斜杠再比对 - 拒绝任何 clean 后包含
".."或开头不是"/"的路径(防绕过)
启动时绑定 localhost 还是 0.0.0.0?
写 http.ListenAndServe(":8080", handler) 默认监听 0.0.0.0:8080,意味着本机所有网卡(包括 WiFi、虚拟网卡、Docker bridge)都开放。如果你只希望同事从隔壁工位连,却忘了防火墙或路由器设置,可能意外暴露到公网。
性能影响小,但安全边界非常明确:局域网共享 ≠ 全网可访。
实操建议:
- 查本机局域网 IP(比如
192.168.1.5),显式绑定:http.ListenAndServe("192.168.1.5:8080", handler) - 若需兼容多网段(如同时有
192.168.x.x和10.x.x.x),才用0.0.0.0,但必须配合前面的 IP 白名单中间件 - macOS 上注意
lo0回环地址(127.0.0.1)无法被其他设备访问,绑它就等于只给自己用
真正麻烦的从来不是写几行 Go 启服务,而是权限逻辑漏掉一种情况、路径校验少判一个符号、或者绑定地址想当然——这些地方一松动,局域网共享就从便利工具变成风险入口。










