Golang 实现简单WebDAV系统 您所在的位置:网站首页 搭建webdav云盘 Golang 实现简单WebDAV系统

Golang 实现简单WebDAV系统

2023-07-28 15:14| 来源: 网络整理| 查看: 265

当前有一台Windows Server的文件服务器,为了方便文件的存储和读取,不想使用网页(云盘)的形式发布到公网,于是想到能否用WebDav的方式来挂载硬盘在本地电脑的文件管理器中。

接下来就是折腾过程的记录

WebDAV (Web-based Distributed Authoring and Versioning) 一种基于HTTP1.1协议的通信协议。它扩展了HTTP 1.1,在GET、POST、HEAD等几个HTTP标准方法以外添加了一些新的方法,使应用程序可对Web Server直接读写,并支持写文件锁定(Locking)及解锁(Unlock),还可以支持文件的版本控制。

尝试PHP

由于WebDAV就是一个Web Sever,于是首先想到的就是用PHP,也是由于用得顺手。随之而来的就是服务器使用Apache还是Nginx?最终选择最简答的PHPStudy懒人包,集成PHP所需要的环境。

使用PHP的一个缺点就是运行环境复杂,需要控制的点太多。Windows Firewall尝试了很多次配置,都还是无法公网访问网页。于是逐渐放弃...

初见Caddy

紧接着开始了搜索简便搭建WebDAV的方式,一个标题 “用Caddy搭建WebDAV服务器” 吸引住我了,一看只需几行简简单单的配置就能开启一个WebDav服务器,于是马上上手。

Action speak louder than words!

在Caddy官网下载了运行文件,按照文中的配置,信心满满敲下命令,报错了!!原来Caddy已经升级到v2版本了,而网上找的文章基本全是v1版本的教程。于是只能一步步慢慢读官方 Document,终于将配置文件修改好了。

Caddy 2 is a powerful, enterprise-ready, open source web server with automatic HTTPS written in Go

在v1中WebDAV是一个内置的包,而在v2中需要在下载是勾选编译,得到的可运行文件才是包含WebDAV的,且v2的WebDAV插件实现的功能更少了,也不是和v1一样的维护者。对于authentication,在v2中已经使用哈希加密存储的方式了。

# First Caddyfile for Webdav :8080 { encode gzip basicauth / { test XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX } webdav /{ root E:\caddy } }

紧接着,测试时发现WebDAV正常运行,也可以连接,但是文件夹是锁定无法读写的。当时也不知道咋回事,看了源码也不懂于是陷入沉思。

Go实现WebDAV

突然发现源码中其实也是importgolang.org/x/net/webdav的库,为何不能直接用Go来实现呢?经过一番努力搜索,出来了个初版。

package main import ( "flag" "fmt" "golang.org/x/net/webdav" "net/http" ) func main() { var addr *string var path *string addr = flag.String("addr", ":8080", "") // listen端口,默认8080 path = flag.String("path", ".", "") // 文件路径,默认当前目录 flag.Parse() fmt.Println("addr=", *addr, ", path=", *path) // 在控制台输出配置 http.ListenAndServe(*addr, &webdav.Handler{ FileSystem: webdav.Dir(*path), LockSystem: webdav.NewMemLS(), }) }

如此简陋,没有密码、没有运行错误判断、没有日志,But it works well! 因为没有接触过Go,完全不知道如何修改。又是一顿骚操作,密码验证的版本来了。

package main import ( "flag" "fmt" "golang.org/x/net/webdav" "net/http" ) func main() { var addr *string var path *string // addr = flag.String("addr", ":8080", "") path = flag.String("path", ".", "") flag.Parse() fs := &webdav.Handler{ FileSystem: webdav.Dir(*path), LockSystem: webdav.NewMemLS(), } http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { // 获取用户名/密码 username, password, ok := req.BasicAuth() if !ok { w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`) w.WriteHeader(http.StatusUnauthorized) return } // 验证用户名/密码 if username != "user" || password != "123456" { http.Error(w, "WebDAV: need authorized!", http.StatusUnauthorized) return } fs.ServeHTTP(w, req) }) fmt.Println("addr=", *addr, ", path=", *path) http.ListenAndServe(*addr, nil) }

但是如果这样的话,数据将是用HTTP在网络明文上传输,这和裸奔有什么区别???安全还是很重要的,遂有了HTTPS版本。

package main import ( "flag" "fmt" "net/http" "os" "golang.org/x/net/webdav" ) var ( flagRootDir = flag.String("dir", "", "webdav root dir") flagHttpAddr = flag.String("http", ":80", "http or https address") flagHttpsMode = flag.Bool("https-mode", false, "use https mode") flagCertFile = flag.String("https-cert-file", "cert.pem", "https cert file") flagKeyFile = flag.String("https-key-file", "key.pem", "https key file") flagUserName = flag.String("user", "", "user name") flagPassword = flag.String("password", "", "user password") flagReadonly = flag.Bool("read-only", false, "read only") ) func init() { flag.Usage = func() { fmt.Fprintf(os.Stderr, "Usage of WebDAV Server\n") flag.PrintDefaults() } } func main() { flag.Parse() fs := &webdav.Handler{ FileSystem: webdav.Dir(*flagRootDir), LockSystem: webdav.NewMemLS(), } http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { if *flagUserName != "" && *flagPassword != "" { username, password, ok := req.BasicAuth() if !ok { w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`) w.WriteHeader(http.StatusUnauthorized) return } if username != *flagUserName || password != *flagPassword { http.Error(w, "WebDAV: need authorized!", http.StatusUnauthorized) return } } if *flagReadonly { switch req.Method { case "PUT", "DELETE", "PROPPATCH", "MKCOL", "COPY", "MOVE": http.Error(w, "WebDAV: Read Only!!!", http.StatusForbidden) return } } fs.ServeHTTP(w, req) }) if *flagHttpsMode { fmt.Println("HTTPS", "addr=", *flagHttpAddr, ", path=", *flagRootDir) http.ListenAndServeTLS(*flagHttpAddr, *flagCertFile, *flagKeyFile, nil) } else { fmt.Println("HTTP", "addr=", *flagHttpAddr, ", path=", *flagRootDir) http.ListenAndServe(*flagHttpAddr, nil) } }

光有HTTPS还需要有证书,于是又用OpenSSL给服务器生成了一个自证书,但是这个问题就导致在Windows上直接连接时一直报错无法连接,由于不是可信任证书或者是无证书(证书生成和颁发这一块不是很清楚,后续学习补充);但是可以使用RaiDrive来正常挂载了😀。如下是运行命令及使用,已经基本可以满足使用了。

E:\caddy>webdav_2.exe -dir E:\SDWAN -http :8080 -https-key-file ./ssl/server.key -https-cert-file ./ssl/server.crt -https-mode -user test -password test E:\caddy>webdav_2.exe -help Usage of WebDAV Server -dir string webdav root dir -http string http or https address (default ":80") -https-cert-file string https cert file (default "cert.pem") -https-key-file string https key file (default "key.pem") -https-mode use https mode -password string user password -read-only read only -user string user name E:\caddy> PPAP

I have a pen I have an apple ah Apple pen

I have a pen I have a pineapple ah Pineapples pen

Apple pen Pineapple pen ah Pen pineapple Apple Pen

查看Caddy是可以用于反向代理的,且Caddy可以自动免费注册SSL证书,就差一个域名,恰巧Freenom可以白嫖域名,于是马上开启白嫖模式。(注意Freenom注册的时候需要美国IP哦)

域名注册好了,一切准备就绪,用Caddy做代理白嫖HTTPS,然后再运行一个最简单的WebDAV,同时增加一个访问日志记录便于后期审计。PREFECT!

# Final Caddyfile example.com:1234 { encode gzip basicauth /* { test XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX } reverse_proxy 127.0.0.1:8080 log { output file ./log/access.log { roll_size 1gb roll_keep 20 } format json } }

大功告成!



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有