Python中如何实现一个简单的带basic auth验证的文件共享服务

源码在:
https://github.com/brightman/dumbo/blob/master/client/dumbo.py
用法如下:
python3 client/dumbo.py -a admin1:admin1
-a 验证的用户名密码
-d 需要共享的目录

其实就是简单修改了一下 python3 自己的 SimpleHTTPRequestHandler,如果结合 ngrok 使用,你可以很方便在本地起一个文件共享服务,临时让别人下载。
差不多 6 年没编码了,如果有错误见谅。

v2ex 怎么上传图片?好久没用了~
Python中如何实现一个简单的带basic auth验证的文件共享服务


2 回复

我来给你一个用Python内置模块实现的简单带Basic Auth验证的文件共享服务。

import http.server
import socketserver
import base64
import os
from urllib.parse import urlparse, unquote

class AuthHTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
    """带Basic Auth验证的HTTP请求处理器"""
    
    def __init__(self, *args, **kwargs):
        # 设置用户名和密码
        self.username = "admin"
        self.password = "password123"
        super().__init__(*args, **kwargs)
    
    def do_GET(self):
        """处理GET请求"""
        # 检查认证头
        auth_header = self.headers.get('Authorization')
        
        if not auth_header or not self.check_auth(auth_header):
            # 认证失败,返回401
            self.send_response(401)
            self.send_header('WWW-Authenticate', 'Basic realm="File Server"')
            self.send_header('Content-type', 'text/html')
            self.end_headers()
            self.wfile.write(b'Authentication required')
            return
        
        # 认证成功,调用父类的do_GET方法
        super().do_GET()
    
    def check_auth(self, auth_header):
        """验证Basic Auth"""
        try:
            # Basic Auth格式: "Basic base64(username:password)"
            auth_type, auth_string = auth_header.split(' ', 1)
            if auth_type.lower() != 'basic':
                return False
            
            # 解码base64
            decoded = base64.b64decode(auth_string).decode('utf-8')
            username, password = decoded.split(':', 1)
            
            # 验证用户名密码
            return username == self.username and password == self.password
        except:
            return False
    
    def translate_path(self, path):
        """重写路径转换,限制访问当前目录"""
        # 解析路径
        parsed_path = urlparse(path)
        path = unquote(parsed_path.path)
        
        # 安全限制:只允许访问当前目录下的文件
        if path.startswith('/'):
            path = path[1:]
        
        # 获取绝对路径
        abs_path = os.path.abspath(os.path.join(os.getcwd(), path))
        
        # 确保路径在当前目录内
        if not abs_path.startswith(os.getcwd()):
            return os.path.join(os.getcwd(), '403.html')  # 返回禁止访问页面
        
        return abs_path

def run_server(port=8000):
    """启动文件共享服务器"""
    handler = AuthHTTPRequestHandler
    
    with socketserver.TCPServer(("", port), handler) as httpd:
        print(f"文件共享服务已启动,访问地址: http://localhost:{port}")
        print(f"用户名: {handler.username},密码: {handler.password}")
        print("按 Ctrl+C 停止服务器")
        
        try:
            httpd.serve_forever()
        except KeyboardInterrupt:
            print("\n服务器已停止")

if __name__ == "__main__":
    # 设置端口
    PORT = 8000
    
    # 启动服务器
    run_server(PORT)

这个实现有几个关键点:

  1. Basic Auth验证:继承SimpleHTTPRequestHandler,重写do_GET方法添加认证检查
  2. 安全路径限制:重写translate_path确保只能访问当前目录下的文件
  3. 简单配置:直接在类里设置用户名密码(生产环境应该从配置文件读取)

使用方法:

  1. 保存为file_server.py
  2. 在终端运行:python file_server.py
  3. 浏览器访问:http://localhost:8000
  4. 输入用户名admin,密码password123

如果需要更复杂的认证,可以考虑用Flask或FastAPI框架。


目前在用 caddy 的插件,哈哈哈

回到顶部