天下苦校园网久矣。

每次电脑刚从休眠中唤醒,系统就会迫不及待地弹出一个又丑又慢的 Dr.COM 认证网页。最搞心态的是,有时候你手速极快地点了登录,它还幽幽地给你吐出一句“AC认证失败”,逼着你刷新重来。

为了这种毫无营养的操作每天浪费十几秒,简直是对程序猿的一种侮辱。既然忍不了,那就动手把它扬了。今天没闲着,顺手把安大的校园网认证逻辑扒了个底朝天,搓了个插网线即刻连网的小玩意儿。
(4/30补充:竟然有师傅提Issue,感动,含泪修bug)
(5/12补充:又出bug了,感觉在这玩意儿花费的时间够我点四年“开机认证”了)
(5/26补充:还有高手,这老古董真会耍性子,半个月不管就罢工给我看)

遇事不决,抓个包先

一开始,我脑子里闪过一个极其暴力的念头:用 Selenium 搞个无头浏览器,模拟人工去点击那个“登录”按钮。但转念一想,为了发这么小的一个认证请求,去跑几十兆的浏览器内核?纯粹大炮打蚊子。

任何华丽的 Web 前端,扒掉那层 HTML/CSS 的皮,本质上都是在向服务器发送 HTTP 请求。

于是,我连上校园网,面对那个万恶的登录弹窗,果断按下了 F12 打开开发者工具,切到 Network (网络) 面板,勾选上 Preserve log(保留日志,防止页面跳转把抓包记录冲掉)。

接着,输入账号密码,点击登录。

果不其然,在眼花缭乱的网络请求列表里,一条状态码为 200 的 GET 请求暴露了它的底牌。点开这条请求的 Payload(载荷)一看,里面的参数直白得让人发笑:

  • DDDDD: 我的宽带账号
  • upass: 我的明文密码
  • wlan_user_ip: 我电脑当前的内网 IP
  • 还有几个看着像时间戳和固定签名的无聊参数。

原来如此。 这套老旧的计费系统为了规避浏览器的一些跨域限制,在 801 端口开放了一个基于 JSONP 的接口。所谓点击登录,其实就是浏览器把你的账号密码拼接成了一段超长的 URL 网址,然后向这个端口发了个快递而已。

既然看破了手脚,接下来的事情就太简单了。几十行 Python 代码,引入 requests 库,先用一个底层 socket 探针拿到本机的内网 IP,然后把参数按照抓包抓到的格式用字典拼好,requests.get(url, params=payload) 一发入魂。终端里立刻返回了 {"result": 1} 的成功响应。

根本不需要什么网页,一个简单的发包脚本,网络就通了。

扔掉死循环,寻找更优雅的方案

发包脚本写好了,怎么让它自动运行?

网上一搜“校园网自动登录”,一堆教程都在教你写个脚本常驻后台,里面套一个无尽的死循环 while True,每隔 5 秒去 ping 一下百度,ping 不通就触发登录脚本。

这方法管用,但极其难看。这种粗暴的轮询不仅一直占用系统的后台进程,还会无端消耗内存和 CPU。

真正的自动化,应该是“事件驱动”的。

我去翻了翻 Windows 的系统底层机制。发现当你插上网线,或者电脑连上路由器的瞬间,Windows 的内核是知道的。它会在系统的事件查看器(Event Viewer)里,往 Microsoft-Windows-NetworkProfile/Operational 这个日志路径下,精准地拍下一条 Event ID 10000 的记录,代表“网络链路已建立”。

这就好办了。这就相当于系统自带了一个极其灵敏的传感器。

我写了个几十行的 .bat 部署脚本,利用 Windows 自带的任务计划程序(Task Scheduler),把刚刚写好的 Python 发包程序直接绑在这个 Event ID 10000 上。

最终的效果爽到起飞:平时,这个工具的 CPU 和内存占用严格等于 0,因为它根本就没在运行。只有在网卡亮起的那几毫秒内,系统感应到了变化,瞬间拉起引擎,在黑面把认证包扔过去。等你慢吞吞打开浏览器的时候,底层网络早就绿灯放行了。

踩坑过程与后续思考

代码写完准备开源的时候,惊出一身冷汗——我差点把写着自己账号密码的 Python 源码直接 git push 上去给全网发福利了。

为了安全,我重构了一下,把账号密码从代码里抽离了出来。在运行 .bat 部署脚本时,会让用户自己输入密码,然后生成一个本地的 .env 环境变量文件藏在文件夹里。Python 脚本只管读取,不负责存储,顺手把 .env 加进了 Git 的忽略名单。

为了让非计算机专业的小白同学也能直接用,最后请出了 PyInstaller,加上 --noconsole --onefile 参数,把 Python 环境和代码全压成了一个不用安装任何依赖、连运行黑框都没有的单体 .exe 文件。

尾声

把所有东西打包扔上了 GitHub Release,顺便补了个 README 说明。

写代码的过程中就在想,这套思路其实绝不仅限于安大。国内大批采用类似 Dr.COM 网页认证的高校,其实底子都一样。只要稍微改一下那个 Python 的抓包请求体,这套“Windows 事件监听 + 局域网物理隔离凭证 + 单体发包”的骨架,可以直接套用到任何学校的头上去。

后来在 GitHub 上搜了一下,发现早在 22 年就有学长用类似的思路搞过工具了。不过没事,权当是一次从协议逆向到系统底层接口调用的全栈练习。折腾了一下午,换来以后每天顺畅无感的开机体验,这波绝对不亏。

代码在 GitHub 存了个档,各位师傅如果遇到 bug,欢迎来提 Issue。
🔗 项目地址:AHU_AutoLogin

尾声的尾声:666还有第二关

原以为这个小工具完成后,就能长期稳定地在后台安静工作。但实际使用一段时间后,还是遇到了一些新的问题:重启电脑后偶尔无法正常联网,拔插网线后表现又不完全一致;有时认证脚本已经执行,浏览器却仍然打不开网页。

气笑了,排查之后发现,这并不是单一代码错误,而是旧版本中几个环境假设逐渐失效导致的。于是对项目做了一次适配更新,发布了 v1.1.0 版本。

5.1 校园网 IP 段变化

旧版为了避免抓到虚拟网卡、无线网卡、热点等非目标网卡的 IP,做了一个简单的 IP 白名单判断,只允许部分校园网常见网段参与认证。

这个思路本身没问题,但后续实际环境中,有线校园网可能会分配到新的 172.21.x.x 网段。于是就出现了一个比较尴尬的情况:脚本已经拿到了正确的有线网卡 IP,却因为白名单过窄,被误判为无效地址。

我chovy,IP给我拿好的啊

因此,v1.1.0 扩展了默认 IP 前缀识别范围:

1
2
3
10.
172.16.
172.21.

同时将这部分配置放入 .env

1
CAMPUS_IP_PREFIXES=10.,172.16.,172.21.

这样后续如果校园网 IP 段再次变化,只需要修改配置文件,不必重新改源码和打包。

5.2 认证接口路径变化

旧版使用的认证路径类似:

1
/eportal/portal/login

但在当前环境下,该路径已经会返回:

1
404 Not Found

重新抓包和探测后,确认当前可用的认证入口为:

1
http://172.16.253.3:801/eportal/

通过 GET 参数携带:

1
2
3
4
5
c=Portal
a=login
user_account=账号
user_password=密码
wlan_user_ip=本机校园网 IP

接口返回仍然是 JSONP 风格,例如:

1
dr1003({"result":"0","msg":"","ret_code":2})

这里的 ret_code=2 不能简单理解为失败。结合实际测试结果,它通常表示当前 IP 已经在线,属于重复认证或已认证状态。因此新版也将该状态纳入成功判断。

5.3 多网卡环境下的等待逻辑

Windows 在插入网线时会很快产生网络状态变化事件,任务计划也会随之触发脚本。但此时 DHCP 分配和路由表更新未必已经完成。

实际排查中发现,脚本启动初期可能先拿到无线网卡或虚拟网卡的 IP,几秒后才切换到真实的有线校园网 IP。如果脚本在第一时间直接发包,就可能因为 IP 不匹配而认证失败。

因此,v1.1.0 保留并强化了等待逻辑:

  1. 先探测校园网 Portal 网关;
  2. 获取当前通往该网关的本机出口 IP;
  3. 判断该 IP 是否属于校园网段;
  4. 如果不是,则继续等待;
  5. 直到识别出真实有线校园网 IP 后再发送认证请求。

这个逻辑对多网卡环境比较重要,尤其是同时存在无线网卡、虚拟机网卡、子系统虚拟网卡或本地代理网络组件时。

5.4 系统代理残留问题

这次排查中还有一个容易被误判的问题:系统代理残留。

如果之前使用过本地代理软件,Windows 可能会保留类似下面这样的本地代理配置:

1
127.0.0.1:7890

如果重启后代理客户端没有启动,但系统代理仍然开启,浏览器流量就会继续发往这个本地端口。此时校园网认证可能已经成功,但浏览器依然无法正常访问网页。

因此,新版发布包中加入了:

1
clear_proxy.ps1

用于清理当前用户的系统代理配置。安装时也可以选择创建登录后自动清理代理残留的任务,减少这类问题对浏览器访问的影响。

5.5 部署方式调整

旧版为了方便使用,使用了中文命名的 .bat 部署脚本。但在部分 Windows 环境下,复杂批处理脚本容易受到编码、换行和转义符影响,出现乱码或命令解析错误。

因此,v1.1.0 将部署方式调整为:

1
2
install.bat
install.ps1

其中 install.bat 只负责启动 PowerShell,真正的安装逻辑放在 install.ps1 中。这样既保留了普通用户“右键管理员运行”的使用方式,也减少了复杂批处理脚本带来的兼容性问题。

5.6 v1.1.0 更新内容

本次更新主要包括:

1
2
3
4
5
6
7
8
- 修复旧版 /eportal/portal/login 返回 404 的问题
- 当前认证入口适配为 /eportal/?c=Portal&a=login
- 新增 172.21.x.x 校园网 IP 段支持
- 优化多网卡环境下的 IP 识别
- 将 ret_code=2 识别为“已在线”状态
- 安装方式改为 install.bat + install.ps1
- 新增 clear_proxy.ps1,用于处理系统代理残留
- 改进日志输出,便于后续排障

修复后,工具重新恢复到了预期状态:插入网线后等待数秒,后台自动完成认证,用户无需手动打开登录网页。

5.7 小结

这次修复最大的体会是:自动化工具真正容易失效的地方,往往不是代码本身,而是代码所依赖的外部环境。

旧版默认了几个条件:

1
2
3
4
5
校园网 IP 段基本稳定
Portal 认证接口路径基本稳定
插网线后路由表会很快稳定
系统代理配置不会影响浏览器访问
批处理脚本在不同 Windows 环境下表现一致

实际使用证明,这些条件都可能发生变化。

所以新版的思路也做了调整:减少硬编码,增加等待机制,保留运行日志,把容易变化的部分配置化。这样后续即使校园网环境再次变化,也能更快定位问题。

最新版已经发布到 GitHub Release:

1
AHU_AutoLogin_v1.1.0.zip

完整解压后,右键以管理员身份运行:

1
install.bat

按提示输入校园网账号和密码即可。

什么?你问我5.2-5.7为什么班味这么重?哥们拿宝贵的假期时间修这搞人的bug,哪有心思扣字眼,直接AI一把梭
唉,博客都快写成说明书了,也许我是天生牛马圣体吧

🔗 项目地址:AHU_AutoLogin