重构Cookie监控系统:添加Web管理后台、Vue3前端界面、Cookie Cloud参数支持、5秒倒计时自动刷新、专业UI配色

This commit is contained in:
bwstudio
2026-04-17 22:37:28 +08:00
parent ed95ce5b23
commit 70802b9b50
44 changed files with 2923 additions and 3654 deletions
+7
View File
@@ -0,0 +1,7 @@
"""Cookie监控管理系统 - 检测客户端"""
import time
import requests
from datetime import datetime
from typing import Dict, List
from DrissionPage import ChromiumPage, ChromiumOptions
from utils.config import BACKEND_URL, BROWSER_TYPE, HEADLESS_MODE
+512
View File
@@ -0,0 +1,512 @@
"""
Cookie监控管理系统 - 检测客户端
前端启动时,不需要登录后端,直接读取所有用户需要登录的网站,
然后分用户、分网站登录。
"""
import time
import requests
from datetime import datetime
from typing import Dict, List, Optional
from DrissionPage import ChromiumPage, ChromiumOptions
from config.config import BACKEND_URL, BROWSER_TYPE, HEADLESS_MODE, PAGE_LOAD_TIMEOUT
class DetectionClient:
"""检测客户端"""
def __init__(self):
self.backend_url = BACKEND_URL
self.browser = None
self.failed_websites = [] # 记录失败的网站
def init_browser(self):
"""初始化浏览器"""
co = ChromiumOptions()
if BROWSER_TYPE == 'edge':
co.set_browser_path(r"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe")
co.set_argument('--no-sandbox')
co.set_argument('--disable-dev-shm-usage')
if HEADLESS_MODE:
co.set_argument('--headless')
self.browser = ChromiumPage(addr_or_opts=co)
print("浏览器初始化成功")
def close_browser(self):
"""关闭浏览器"""
if self.browser:
try:
self.browser.quit()
except Exception as e:
print(f"关闭浏览器失败: {e}")
finally:
self.browser = None
def get_all_users(self) -> List[Dict]:
"""获取所有用户"""
try:
response = requests.get(f"{self.backend_url}/api/users")
response.raise_for_status()
return response.json()
except requests.RequestException as e:
print(f"获取用户失败: {e}")
return []
def get_user_websites(self, user_id: int) -> List[Dict]:
"""获取用户的网站列表"""
try:
response = requests.get(f"{self.backend_url}/api/websites?user_id={user_id}")
response.raise_for_status()
return response.json()
except requests.RequestException as e:
print(f"获取用户 {user_id} 的网站失败: {e}")
return []
def get_website_cookies(self, website_id: int) -> List[Dict]:
"""获取网站的cookie"""
try:
response = requests.get(f"{self.backend_url}/api/cookies/websites/{website_id}")
response.raise_for_status()
return response.json()
except requests.RequestException as e:
print(f"获取网站 {website_id} 的cookie失败: {e}")
return []
def update_website_cookies(self, website_id: int, cookies: List[Dict]):
"""更新网站的cookie"""
try:
response = requests.put(
f"{self.backend_url}/api/cookies/websites/{website_id}",
json={'cookies': cookies}
)
response.raise_for_status()
print(f"网站 {website_id} 的cookie已更新")
except requests.RequestException as e:
print(f"更新网站 {website_id} 的cookie失败: {e}")
def save_detection_result(self, website_id: int, status: int, response_time: float,
http_status: int, message: str):
"""保存检测结果"""
try:
response = requests.post(
f"{self.backend_url}/api/detections",
json={
'website_id': website_id,
'status': status,
'response_time': response_time,
'http_status': http_status,
'message': message
}
)
response.raise_for_status()
except requests.RequestException as e:
print(f"保存检测结果失败: {e}")
def send_notification(self, user_id: int, website_id: int, title: str, content: str):
"""发送通知"""
try:
response = requests.post(
f"{self.backend_url}/api/notifications",
json={
'user_id': user_id,
'website_id': website_id,
'title': title,
'content': content
}
)
response.raise_for_status()
print(f"通知已发送")
except requests.RequestException as e:
print(f"发送通知失败: {e}")
def import_cookies_to_browser(self, cookies: List[Dict], domain: str) -> int:
"""导入cookies到浏览器"""
if not self.browser or not cookies:
return 0
success_count = 0
for cookie in cookies:
try:
if not cookie.get('name') or not cookie.get('value'):
continue
cookie_dict = {
'name': cookie.get('name'),
'value': cookie.get('value'),
'domain': cookie.get('domain', domain),
'path': cookie.get('path', '/')
}
self.browser.set.cookies(cookie_dict)
success_count += 1
except Exception as e:
print(f"导入cookie失败: {e}")
return success_count
def verify_login(self, url: str, check_selector: str = "", success_text: str = "") -> bool:
"""
验证登录状态
Args:
url: 网站地址
check_selector: 登录检测选择器
success_text: 登录成功时显示的文本
Returns:
是否已登录
"""
if not self.browser:
return False
try:
self.browser.get(url)
self.browser.wait.doc_loaded(timeout=PAGE_LOAD_TIMEOUT)
time.sleep(3)
# 刷新页面几次确保登录状态
for i in range(3):
time.sleep(3)
self.browser.refresh()
self.browser.wait.doc_loaded(timeout=PAGE_LOAD_TIMEOUT)
time.sleep(3)
if not check_selector and not success_text:
return False
# 检查选择器
if check_selector:
try:
element = self.browser.ele(check_selector, timeout=10)
if element:
element_text = element.text or ""
if not success_text:
return True
if success_text in element_text:
return True
except:
pass
# 检查成功文本
if success_text:
try:
page_text = self.browser.html or ""
if success_text in page_text:
return True
except:
pass
return False
except Exception as e:
print(f"验证登录状态失败: {e}")
return False
def get_current_cookies(self) -> List[Dict]:
"""获取当前浏览器的所有cookies"""
if not self.browser:
return []
try:
return self.browser.cookies()
except Exception as e:
print(f"获取cookies失败: {e}")
return []
def check_website(self, user: Dict, website: Dict) -> bool:
"""
检测单个网站
Args:
user: 用户信息
website: 网站信息
Returns:
是否登录成功
"""
website_id = website.get('id')
website_name = website.get('name')
url = website.get('url')
check_selector = website.get('login_check_selector', '')
success_text = website.get('success_text', '')
print(f"\n检测网站: {website_name} ({url})")
print(f"用户: {user.get('name')}")
start_time = time.time()
try:
# 获取网站的cookie
cookies = self.get_website_cookies(website_id)
if not cookies:
print(f" 警告: 未找到网站 {website_name} 的cookie")
self.save_detection_result(
website_id=website_id,
status=0,
response_time=time.time() - start_time,
http_status=0,
message="未找到cookie"
)
return False
# 导入cookie到浏览器
from urllib.parse import urlparse
parsed = urlparse(url)
domain = parsed.netloc
self.import_cookies_to_browser(cookies, domain)
# 访问网站
self.browser.get(url)
self.browser.wait.doc_loaded(timeout=PAGE_LOAD_TIMEOUT)
time.sleep(3)
# 验证登录状态,如果未登录则以30秒为周期连续检测6次
login_success = self._check_login_with_retry(url, check_selector, success_text)
response_time = time.time() - start_time
if login_success:
print(f" ✓ 登录验证成功")
# 获取最新cookie并保存到后台
current_cookies = self.get_current_cookies()
if current_cookies:
self.update_website_cookies(website_id, current_cookies)
print(f" 已更新cookie ({len(current_cookies)} 个)")
# 保存检测结果
self.save_detection_result(
website_id=website_id,
status=1,
response_time=response_time,
http_status=200,
message="登录验证成功"
)
return True
else:
print(f" ✗ 登录验证失败(连续6次检测未登录)")
# 记录失败信息
self.failed_websites.append({
'user': user,
'website': website,
'reason': '登录验证失败(连续6次检测未登录)'
})
# 保存检测结果
self.save_detection_result(
website_id=website_id,
status=0,
response_time=response_time,
http_status=200,
message="登录验证失败(连续6次检测未登录)"
)
return False
except Exception as e:
response_time = time.time() - start_time
print(f" ✗ 检测异常: {e}")
# 记录失败信息
self.failed_websites.append({
'user': user,
'website': website,
'reason': str(e)
})
# 保存检测结果
self.save_detection_result(
website_id=website_id,
status=0,
response_time=response_time,
http_status=0,
message=f"检测异常: {e}"
)
return False
def _check_login_with_retry(self, url: str, check_selector: str, success_text: str,
retry_count: int = 6, retry_interval: int = 30) -> bool:
"""
检查登录状态,如果未登录则重复检测
Args:
url: 网站地址
check_selector: 登录检测选择器
success_text: 登录成功文本
retry_count: 最大重试次数
retry_interval: 重试间隔(秒)
Returns:
是否登录成功
"""
# 第一次检测
if self._is_logged_in(check_selector, success_text):
return True
print(f" 首次检测未登录,开始周期性检测(最多{retry_count}次,间隔{retry_interval}秒)")
for i in range(1, retry_count + 1):
print(f"{i}/{retry_count} 次检测...")
time.sleep(retry_interval)
# 刷新页面
self.browser.refresh()
self.browser.wait.doc_loaded(timeout=PAGE_LOAD_TIMEOUT)
time.sleep(3)
if self._is_logged_in(check_selector, success_text):
print(f"{i} 次检测登录成功")
return True
return False
def _is_logged_in(self, check_selector: str, success_text: str) -> bool:
"""
判断是否已登录
Returns:
是否已登录
"""
if not check_selector and not success_text:
return False
# 检查选择器
if check_selector:
try:
element = self.browser.ele(check_selector, timeout=10)
if element:
element_text = element.text or ""
if not success_text:
return True
if success_text in element_text:
return True
except:
pass
# 检查成功文本
if success_text:
try:
page_text = self.browser.html or ""
if success_text in page_text:
return True
except:
pass
return False
def send_failed_notifications(self):
"""发送失败网站的通知"""
if not self.failed_websites:
return
print(f"\n发现 {len(self.failed_websites)} 个失败的网站,发送通知")
# 按用户分组
user_notifications = {}
for failed in self.failed_websites:
user_id = failed['user'].get('id')
if user_id not in user_notifications:
user_notifications[user_id] = {
'user': failed['user'],
'websites': []
}
user_notifications[user_id]['websites'].append(failed)
# 为每个用户发送通知
for user_id, notif_data in user_notifications.items():
user = notif_data['user']
websites = notif_data['websites']
# 构建通知内容
content_lines = [
f"**{user.get('name')} Cookie登录报告**",
f"",
f"检测时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}",
f"失败数量: {len(websites)} 个网站",
f"",
"失败详情:"
]
for failed in websites:
website = failed['website']
reason = failed['reason']
content_lines.append(f"- {website.get('name')}: {reason}")
content = "\n".join(content_lines)
# 发送通知
if websites:
self.send_notification(
user_id=user_id,
website_id=websites[0]['website'].get('id'),
title=f"Cookie登录失败 ({len(websites)} 个网站)",
content=content
)
def run_detection_cycle(self):
"""执行一轮检测"""
print(f"\n{'='*50}")
print(f"开始执行检测任务 - {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print(f"{'='*50}")
self.failed_websites = []
# 初始化浏览器
self.init_browser()
try:
# 获取所有用户
users = self.get_all_users()
if not users:
print("未找到用户,跳过检测")
return
print(f"找到 {len(users)} 个用户")
# 分用户处理
for user in users:
print(f"\n处理用户: {user.get('name')}")
# 获取用户的网站
websites = self.get_user_websites(user.get('id'))
if not websites:
print(f" 用户 {user.get('name')} 没有网站,跳过")
continue
print(f" 找到 {len(websites)} 个网站")
# 分网站处理
for website in websites:
if website.get('status', 1) != 1:
print(f" 网站 {website.get('name')} 已禁用,跳过")
continue
self.check_website(user, website)
# 发送失败通知
self.send_failed_notifications()
except Exception as e:
print(f"检测任务执行异常: {e}")
finally:
self.close_browser()
print(f"\n{'='*50}")
print(f"检测任务完成 - {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print(f"{'='*50}")
def run(self):
"""运行检测客户端"""
print("Cookie监控检测客户端启动")
# 执行一轮检测
self.run_detection_cycle()
def main():
"""主函数"""
client = DetectionClient()
client.run()
if __name__ == "__main__":
main()
+15
View File
@@ -0,0 +1,15 @@
"""
配置文件
"""
# 后台服务地址
BACKEND_URL = "http://localhost:5000"
# 浏览器配置
BROWSER_TYPE = "edge" # edge 或 chrome
HEADLESS_MODE = False # 是否无头模式
# 检测间隔(秒)
CHECK_INTERVAL = 30
# 页面加载超时时间(秒)
PAGE_LOAD_TIMEOUT = 30