Files
ykxmz/_build/halo_login3.py
T
xmz7891 2061f9525f 2.3.0:手表界面精简 + 播放器 + 鼠标重做
手表端
- 功能页从 10 个杂项精简到 7 个(屏幕/鼠标/媒体/文件/电脑/语音/电源)
- 删掉:游戏封锁、待办、掷骰子、抽奖、壁纸、显示器开关、定时关机、
  剪贴板历史、性能/磁盘/电量、文件夹浏览、教室限制等
- 改成显式列按钮,不再把电脑端所有功能组无脑铺到表盘
- 远程鼠标控制重做:滑动区 + 左键/滚轮/右键三按钮
  滚轮点按=中键、上下滑=滚动
- 新增视频/音乐播放器(手表本地播放):进度拖动、左右滑快进退10秒、
  点画面播放暂停、上一/下一、播完自动下一首

电脑端
- 新增 kill_all(结束所有进程),白名单保护系统关键进程和自身
- 新增 media_list / media_pull(播放器数据源)
  安全边界:只允许媒体目录,用 relative_to 判断,防同前缀兄弟目录绕过

中转站
- known_devices 从 ID 集合改成「设备ID -> 配对码」映射
- 修复:管理员改码后关机超过 6 小时,改码会被超时清理冲掉
- 老格式 state 文件平滑升级
2026-10-18 11:39:14 +08:00

81 lines
2.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
r'''Halo 登录(第三版):处理 CSRF,然后发文章。
== 前面两次为什么失败 ==
第一版:`Authorization: Basic` -> **302**(Halo 的 console API 不认 Basic,
它要会话 cookie 或 Personal Access Token)
第二版:直接 POST `/login` -> **403**(Spring Security 的 CSRF 保护)
== 这一版 ==
走完整的网页登录流程:
1. GET /login -> 拿 SESSION cookie + HTML 里的 _csrf token
2. POST /login -> 带上 cookie + _csrf + 用户名密码
3. 用返回的会话 cookie 调 console API
CSRF token 通常在登录页的 HTML 里(`<input name="_csrf">` 或 `<meta>`)。
Halo 的登录页是 SPA 还是服务端渲染会影响它在不在 —— 所以脚本会
**两种都找**,找不到就明确报出来,不瞎猜。
== 如果还是不行 ==
那就得让用户在 Halo 后台建一个**个人令牌**(设置 -> 个人令牌),
拿到之后 `Authorization: Bearer <token>` 就能用。
那是最可靠的方式 —— 30 秒的事,而且不用把密码给脚本。
'''
from __future__ import annotations
import json
import re
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(ROOT / "_build"))
from lssh import run # noqa: E402
PWFILE = ROOT / "_build" / ".halo_password"
USER = "xmz7891"
def main() -> int:
print("=" * 62)
print(" Halo 登录(带 CSRF)")
print("=" * 62)
print()
pw = PWFILE.read_text(encoding="utf-8").strip()
out = run(r'''
rm -f /tmp/hc.txt /tmp/login.html
echo "── 1. GET /login(拿 cookie + csrf token)──"
curl -s -c /tmp/hc.txt -o /tmp/login.html \
-w " HTTP %{http_code} %{size_download} 字节 Content-Type: %{content_type}\n" \
--max-time 15 http://127.0.0.1:3001/login
echo " cookie:"
grep -v '^#' /tmp/hc.txt 2>/dev/null | while read -r a b c d e f g; do
[ -n "$f" ] && echo " $f"
done
[ -s /tmp/hc.txt ] || echo " (没拿到 cookie)"
echo
echo " HTML 里找 csrf token:"
grep -oiE '(<input[^>]*name="_csrf"[^>]*>|name="_csrf"[^>]*value="[^"]*"|"csrf[a-zA-Z]*"\s*:\s*"[^"]*"|csrf-token[^>]*content="[^"]*")' /tmp/login.html 2>/dev/null | head -5 | sed 's/^/ /'
echo " HTML 前 400 字:"
head -c 400 /tmp/login.html | tr -d '\n' | sed 's/^/ /'
echo
echo
echo " title:"
grep -oiE '<title>[^<]*</title>' /tmp/login.html 2>/dev/null | head -2 | sed 's/^/ /'
''', timeout=240, quiet=True)
print(out[1] if isinstance(out, tuple) else out)
return 0
if __name__ == "__main__":
sys.exit(main())