那么根据我的提供的代码帮我添加一下,在HTTP模式下登录成功,对该用户名添加cookie和httponly
from utils import USER_FILE, UPLOAD_DIR, DOWNLOAD_DIR, load_users, save_user, check_user, check_user_md5
from bottle import Bottle, static_file, redirect, request, run, template, BaseRequest, response
from bottle_auth import AuthPlugin
import hashlib
import os
import ctypes
import tarfile
import tempfile
from routes_en import setup_routes_en, cleanup_tar_files
import threading
import time
USER_FILE = '/mnt/usrfs/webTest/user_auth.txt'
UPLOAD_DIR = '/mnt/usrfs/upload'
DOWNLOAD_DIR = '/mnt/usrfs/'
BaseRequest.MEMFILE_MAX = 1024 * 1024 * 15 # 15MB
# 5. 自定义 AuthPlugin,支持md5密码
class MD5AuthPlugin(AuthPlugin):
def __init__(self, users):
super().__init__(users)
def check_auth(self, username, password):
# password是明文,转md5后比对
pwd_md5 = hashlib.md5(password.encode()).hexdigest()
return check_user_md5(username, pwd_md5)
def require(self, f):
def check_auth(*args, **kwargs):
username = request.auth[0] if request.auth else None
password = request.auth[1] if request.auth else None
if not username or not password:
response.headers['WWW-Authenticate'] = 'Basic realm=\"Login Required\"'
response.status = 401
return "Authentication required"
if not self.check_auth(username, password):
response.headers['WWW-Authenticate'] = 'Basic realm=\"Login Required\"'
response.status = 401
return "Authentication failed"
return f(*args, **kwargs)
return check_auth
# 6. 创建 Bottle 应用
app = Bottle()
users = load_users()
auth = MD5AuthPlugin(users)
app.install(auth)
setup_routes_en(app,auth)
# 启动清理线程
if __name__ == '__main__':
# 如果没有用户文件,自动创建一个默认用户
if not os.path.exists(USER_FILE):
save_user('root', 'root')
# 使用最简单的配置
t = threading.Thread(target=cleanup_tar_files, daemon=True)
t.start()
app.run(host='0.0.0.0', port=80, debug=False, reloader=False)以上是main;from utils import USER_FILE, UPLOAD_DIR, DOWNLOAD_DIR, check_user
from bottle import static_file, redirect, request, template, response
from bottle import template
from page_generators_en import get_basic_info_html_en, get_dev_status_html_en
import tarfile
import os
import time
from vtysh_cmd_send import VtyshCommandExecutor
USER_FILE = '/mnt/usrfs/webTest/user_auth.txt'
UPLOAD_DIR = '/mnt/usrfs/upload'
DOWNLOAD_DIR = '/mnt/usrfs/'
def setup_routes_en(app, auth):
@app.route('/www/baseMsg_en.asp')
def basic_info_www_en():
html = get_basic_info_html_en()
return template('basic_info_en', basic_info_html_en=html)
@app.route('/www/devStatus_en.asp')
def dev_status_www_en():
html = get_dev_status_html_en()
return template('dev_status_en', dev_status_html_en=html)
@app.route('/www/ipaddr_en.asp')
def ip_config_page():
return template('ip_address_en')
@app.route('/api/execute_ip_config', method='POST')
def execute_ip_config():
try:
# 获取前端发送的配置
config = request.json
# 验证配置
if not config or 'network' not in config:
return {'success': False, 'error': 'Invalid configuration'}
# 使用VtyshCommandExecutor执行配置
from vtysh_cmd_send import VtyshCommandExecutor
executor = VtyshCommandExecutor("../bin/vtysh")
result = executor.execute_config(config)
return result
except Exception as e:
return {'success': False, 'error': str(e)}
# def file_root_en(app):
@app.route('/')
def index():
return redirect('/www/index1/index_en.html')
@app.route('/download_file/<path:path>')
def download_file(path):
print(f"DEBUG: 下载请求路径: {path}") # 调试信息
abs_file = os.path.abspath(os.path.join(DOWNLOAD_DIR, path))
print(f"DEBUG: 绝对文件路径: {abs_file}") # 调试信息
# 检查DOWNLOAD_DIR是否存在
if not os.path.exists(DOWNLOAD_DIR):
print(f"DEBUG: DOWNLOAD_DIR不存在") # 调试信息
return "DOWNLOAD_DIR不存在"
if not abs_file.startswith(os.path.abspath(DOWNLOAD_DIR)):
print(f"DEBUG: 路径安全检查失败") # 调试信息
return "非法路径"
# 检查文件或目录是否存在
if not os.path.exists(abs_file):
print(f"DEBUG: 文件/目录不存在: {abs_file}") # 调试信息
return f"文件/目录不存在: {abs_file}"
# 如果是目录,创建tar文件
if os.path.isdir(abs_file):
print(f"DEBUG: 开始打包目录: {abs_file}")# 调试信息
try:
# 在DOWNLOAD_DIR中创建tar文件,而不是临时目录
tar_filename = os.path.basename(abs_file) + '.tar'
tar_path = os.path.join(DOWNLOAD_DIR, tar_filename)
print(f"DEBUG: tar文件路径: {tar_path}") # 调试信息
# 创建tar文件
with tarfile.open(tar_path, 'w') as tar:
tar.add(abs_file, arcname=os.path.basename(abs_file))
# 检查tar文件是否创建成功
if os.path.exists(tar_path):
file_size = os.path.getsize(tar_path)
print(f"DEBUG: tar文件创建成功,大小: {file_size} 字节") # 调试信息
else:
print(f"DEBUG: tar文件创建失败") # 调试信息
return "tar文件创建失败"
print(f"DEBUG: 目录打包完成: {tar_path}") # 调试信息
print(f"DEBUG: 下载文件名: {tar_filename}") # 调试信息
# 使用static_file返回tar文件
# 设置响应头
response.set_header('Content-Type', 'application/x-tar')
response.set_header('Content-Disposition', f'attachment; filename=\"{tar_filename}\"')
response.set_header('Content-Length', str(file_size))
response.set_header('Accept-Ranges', 'bytes')
# 直接 return 生成器
return generate_with_timeout(tar_path, timeout=60)
except Exception as e:
print(f"DEBUG: 打包目录失败: {e}") # 调试信息
return f"打包目录失败: {e}"
# 如果是文件,直接下载
if not os.path.isfile(abs_file):
print(f"DEBUG: 不是普通文件: {abs_file}") # 调试信息
return f"不是普通文件: {abs_file}"
# 检查文件权限
if not os.access(abs_file, os.R_OK):
print(f"DEBUG: 文件没有读取权限: {abs_file}") # 调试信息
return f"文件没有读取权限: {abs_file}"
print(f"DEBUG: 文件存在,开始下载: {abs_file}") # 调试信息
filename = os.path.basename(abs_file)
print(f"DEBUG: 下载文件名: {filename}") # 调试信息
# 使用正确的MIME类型和文件名
return static_file(filename, root=os.path.dirname(abs_file), download=filename)
@app.route('/<filepath:path>')
def serve_static(filepath):
return static_file(filepath, root='/mnt/usrfs/')
# 表单登录
@app.route('/action/login', method='POST')
def do_login():
username = request.forms.get('username')
password = request.forms.get('password')
if check_user(username, password):
return redirect('/www/index_en.htm')
else:
return "Login failed!"
# 受保护路由
@app.route('/protected')
@auth.require
def protected():
return "你已通过 HTTP Basic Auth 认证!"
@app.route('/www/web_upload_file_en.asp', method=['GET', 'POST'])
def web_upload_file_en():
if request.method == 'GET':
return template('upload_en') # 注意这里是 upload._en
else:
upload_file = request.files.get('uploadfile')
if not upload_file or not upload_file.filename:
return "<p style='color:red'>没有选择文件!</p>"
save_path = os.path.join(UPLOAD_DIR, upload_file.filename)
upload_file.save(save_path, overwrite=True)
return f"<p style='color:green'>文件已上传到: {save_path}</p><a href='/www/web_upload_file_en.asp'>返回</a>"
@app.route('/filebrowser')
@app.route('/filebrowser/<path:path>')
def filebrowser(path=''):
print(f"DEBUG: 访问路径: {path}") # 调试信息
abs_dir = os.path.abspath(os.path.join(DOWNLOAD_DIR, path))
print(f"DEBUG: 绝对路径: {abs_dir}") # 调试信息
if not abs_dir.startswith(os.path.abspath(DOWNLOAD_DIR)):
print(f"DEBUG: 路径安全检查失败") # 调试信息
return "非法路径"
if not os.path.isdir(abs_dir):
print(f"DEBUG: 目录不存在: {abs_dir}") # 调试信息
return "目录不存在"
items = []
for fname in sorted(os.listdir(abs_dir)):
fpath = os.path.join(abs_dir, fname)
is_dir = os.path.isdir(fpath)
items.append({'name': fname, 'is_dir': is_dir})
parent = os.path.dirname(path) if path else None
print(f"DEBUG: 父目录: {parent}") # 调试信息
return template('download_en', items=items, cur_path=path, parent=parent)
def generate_with_timeout(file_path, timeout=60):
start_time = time.time()
with open(file_path, 'rb') as f:
while True:
if time.time() - start_time > timeout:
break
chunk = f.read(1024 * 1024)
if not chunk:
break
yield chunk
def cleanup_tar_files():
while True:
now = time.time()
for fname in os.listdir(DOWNLOAD_DIR):
if fname.endswith('.tar'):
fpath = os.path.join(DOWNLOAD_DIR, fname)
try:
if os.path.isfile(fpath):
# 删除2分钟以前的tar文件
if now - os.path.getmtime(fpath) > 120:
os.remove(fpath)
print(f"DEBUG: 自动清理tar文件: {fpath}")
except Exception as e:
print(f"DEBUG: 清理tar文件失败: {e}")
time.sleep(60) # 每分钟检查一次
以上是route部分
最新发布