diff --git a/webdav_production.py b/webdav_production.py new file mode 100644 index 0000000..8dd44fe --- /dev/null +++ b/webdav_production.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python3 +""" +生产环境WebDAV配置,支持域名部署 +""" + +import os +from pathlib import Path +from wsgidav.wsgidav_app import WsgiDAVApp +from wsgidav.fs_dav_provider import FilesystemProvider +from wsgidav.http_authenticator import HTTPAuthenticator + + +class DomainDomainController: + """支持域名的域控制器""" + + def __init__(self, wsgidav_app, config): + self.wsgidav_app = wsgidav_app + self.config = config + + def get_domain_realm(self, path_info, environ): + return "WebDAV" + + def require_authentication(self, realm, environ): + # 生产环境可以启用认证,开发环境暂时关闭 + return False + + def is_authenticated_user(self, realm, user_name, environ): + return True + + def auth_user(self, realm, user_name, password, environ): + return True + + def supports_http_digest_auth(self): + return True + + def is_share_anonymous(self, share): + return True + + +def create_production_webdav_app(domain=None, ssl=False): + """ + 创建生产环境WebDAV应用 + + Args: + domain: 域名,如 'yourdomain.com' + ssl: 是否使用HTTPS + """ + # 确保projects目录存在 + projects_dir = Path("projects") + projects_dir.mkdir(exist_ok=True) + + # 根据域名配置host + if domain: + host = "0.0.0.0" # 生产环境监听所有接口 + scheme = "https" if ssl else "http" + server_url = f"{scheme}://{domain}" + else: + host = "localhost" + server_url = "http://localhost" + + # 配置WebDAV + config = { + "host": host, + "port": 8001, + "provider_mapping": { + "/": FilesystemProvider(str(projects_dir)) + }, + "http_authenticator": { + "domain_controller": DomainDomainController, + "accept_basic": True, + "accept_digest": True, + "default_to_digest": False, + }, + "verbose": 2 if domain else 1, # 生产环境更详细日志 + "dir_browser": { + "enable": True, + "response_trailer": True, + "davmount_path": "/webdav", + "ms_mount_path": "/webdav", + }, + # 添加CORS支持 + "middleware": [ + { + "class": "wsgidav.middleware.cors.CorsMiddleware", + "options": { + "cors_origin": "*", + "cors_methods": "GET, POST, PUT, DELETE, OPTIONS, PROPFIND, MKCOL, COPY, MOVE", + "cors_headers": "Authorization, Content-Type, Depth, Destination, Overwrite", + } + } + ] + } + + # 创建应用 + app = WsgiDAVApp(config) + + print(f"WebDAV Server configured for domain: {domain or 'localhost'}") + print(f"Server URL: {server_url}:8001/webdav") + + return app + + +if __name__ == "__main__": + # 可以通过环境变量配置域名 + domain = os.environ.get("WEBDAV_DOMAIN") + ssl_enabled = os.environ.get("WEBDAV_SSL", "false").lower() == "true" + + app = create_production_webdav_app(domain, ssl_enabled) + + from wsgidav.server.run_server import run_server + run_server(app) \ No newline at end of file diff --git a/webdav_server.py b/webdav_server.py index 17cc169..30e31be 100644 --- a/webdav_server.py +++ b/webdav_server.py @@ -11,23 +11,31 @@ from wsgidav.fs_dav_provider import FilesystemProvider from wsgidav.http_authenticator import HTTPAuthenticator -class NullDomainController: - """空域控制器,跳过认证""" +class SimpleDomainController: + """简单域控制器,支持固定用户名密码认证""" def __init__(self, wsgidav_app, config): - pass + # 简单的用户名密码配置 + self.users = { + "admin": "admin123", # 用户名: admin, 密码: admin123 + "webdav": "webdav123", # 用户名: webdav, 密码: webdav123 + } def get_domain_realm(self, path_info, environ): - return None + return "WebDAV" def require_authentication(self, realm, environ): - return False # 不需要认证 + return False # 暂时不强制认证,兼容性更好 def is_authenticated_user(self, realm, user_name, environ): - return True # 总是认证成功 + return True # 允许任何用户名通过 def auth_user(self, realm, user_name, password, environ): - return True # 总是认证成功 + # 如果用户名为空,允许通过(匿名访问) + if not user_name: + return True + # 检查用户名密码 + return self.users.get(user_name) == password def supports_http_digest_auth(self): return True @@ -55,9 +63,9 @@ def create_webdav_app(): "/": FilesystemProvider(str(projects_dir)) }, "http_authenticator": { - "domain_controller": "webdav_server.NullDomainController", - "accept_basic": False, - "accept_digest": False, + "domain_controller": "webdav_server.SimpleDomainController", + "accept_basic": True, + "accept_digest": True, "default_to_digest": False, }, "verbose": 1, # 日志级别