Skip to main content

campus-auth

PyPI Python CI

河南城建学院校园网(Dr.COM / eportal)的命令行客户端。 一行命令登录,断线自动重连: 不用再点那个 IP 一变就失效的快捷方式,也不用每次手动开浏览器。

非官方、自担风险。 学校没对这类工具出过明确规定,详见免责与风险。

$ campus-auth login -w cmcc
IP 10.138.14.27  MAC AABBCCDDEEFF  账号 ,0,081456789@cmcc
服务端: 认证成功  ret_code=0
结果: 已在线

文里的学号、MAC、IP 都是编的。

门户 适配层 状态
河南城建学院 Dr.COM / eportal huuc 实机验证
其它 Dr.COM 门户 generic 模板,照它改(本项目主要不为它们服务)

范围只有 Dr.COM / eportal。 锐捷(InterFace.do)和深澜(srun_portal)不随包提供: 维护者拿不到真机。probe 仍然能认出它们,认出来会直接告诉你换工具。

English — A CLI for the Dr.COM/eportal campus portal of HUUC (Henan University of Urban Construction), Chinese campus network. One command to log in, auto-reconnect on drops, --json everywhere, exit codes are a contract, passwords go to the OS keyring. Windows / macOS / Linux, Python ≥ 3.10, no runtime dependencies. Other Dr.COM campuses can work through the generic adapter (CONTRIBUTING.md); covered schools live in docs/schools.md.


为什么还需要一个

校园网客户端的老项目大多死在同一处:把一所学校的协议写死在主流程里,第二所学校只能 fork 一份改烂,原仓库最后被几十个分支拖住。这里的约束反过来:核心不认识任何学校,一所学校的 差异只写在适配层里,加学校不改 core。

它解决什么

  • IP 一变就失效的快捷方式:门户的密钥是 wlan_user_ip 的字符异或,DHCP 续租就废。 客户端每次现场算。
  • 断线重连:watch 先查在线列表(一次请求),确认掉线才登录,失败指数退避, 不会把网关点成 QPS 炸弹。
  • 宿舍 / 教学楼的运营商差异:SSID 和网段决定要不要 @cmcc 后缀,选错就是 AC认证失败 —— 客户端会先提示,再把服务端的黑话翻译成人话。
  • 给脚本用:--json 加下面那张退出码表,塞进计划任务和监控都不用解析中文;字段有 schema 版本和稳定性承诺,见 docs/json.md。

装

不会命令行的同学(推荐)

从 Releases 下 campus-auth-<版本>-win.zip, 解压后双击 install.cmd,跟着做就行:它会检查 Python、让你填学号、问一次密码、当场验一遍, 最后问要不要开机自启。包里有 install-guide.txt(步骤)和 disclaimer.txt(风险)。

装之前先连热点或流量 —— 还没认证时下载和 pip 都上不去。

会命令行

pip install campus-auth
pip install "campus-auth[keyring]"   # 可选:把密码交给系统钥匙串

默认无第三方运行时依赖,keyring 是唯一的可选 extra。Python ≥ 3.10。 没有 pip 的机器用单文件:从 Releases 下 campus-auth.pyz,python campus-auth.pyz status。 同一个 Release 里带 SHA256SUMS,sha256sum -c SHA256SUMS 能先核对再跑。

四步上手

setup 一条命令做完:写配置 → 填学号 → 存密码 → 当场验一次 → 问要不要自启。

campus-auth setup

想自己一步步来,或者要改细节:

campus-auth probe                          # 先确认是 Dr.COM,不是别的门户
campus-auth init                           # 生成配置模板
campus-auth password                       # 填完 account 再存密码(不回显)

probe 会从劫持页自己找门户地址;已经在线时也能跑——捞不到就自动退回本校门户地址, 不用你填 IP。只收 HTTPS 的门户会从 http:// 自动重试一次 https://。

init 会打印它用的适配层和门户地址,写成 huuc 只是默认值 —— 不是河南城建学院就换:

campus-auth probe --url https://10.9.8.7:802         # 判成 Dr.COM 再往下
campus-auth init --adapter generic --url https://10.9.8.7:802
campus-auth login --adapter generic --url https://10.9.8.7:802 --ip 10.x.x.x

generic 里的参数名和密钥函数要照你自己抓到的请求改(见 加一所学校); 改好之前 probe 说「证据不全」是正常的。已知学校的清单在 docs/schools.md。

init 之后按提示改 account,然后:

campus-auth status     # 自检:没配好会直接指出来
campus-auth login      # 宿舍网段加 -w cmcc,教学楼不加
campus-auth watch      # 断线自动重连,前台跑

status 会把“门户里有会话”和“会话是你自己的”分开说 —— 前者可能只是上一位用户还没掉线。 出问题先跑 campus-auth doctor:它把排障要的信息一次打全,密码不会出现,可以直接贴进 issue。

第一步的 probe

probe 只请求匿名接口,不要账号密码;只从校园网内有效。不给 --url 时它会打两个公开探针地址, 从劫持页里找门户;捞不到(已在线)就退回适配层地址。--no-discover 关掉发现这一步,--no-follow 不跟劫持页的跳转。

$ campus-auth probe
(没从劫持页找到地址:…;改用适配层地址 https://netauth.huuc.edu.cn:802)
目标 https://netauth.huuc.edu.cn:802
判定: 是 Dr.COM(eportal)   置信度: 中(60 分)

  ✓ 会话接口返回 online_session / online_time (+30)
  ✓ 响应含 ret_code / result 字段 (+15)
  ...
! 门户显示已有在线会话:已在线时 probe 同样有效,登录前不必先注销

判定不是看一条信号:dr1003 只有页面里出现过才算数(Dr.COM 会回显你传的任何 callback), wlan_user_ip、result 这种谁都有的只值低分。要判成「是 Dr.COM」,除了分数过 55 分、 领先第二名 10 分,还必须命中 enc_pwd / getkey / 会话接口的 online_session 这类独有特征; 凑不够就只说「像」,并列出还缺哪些证据。

probe 说 怎么办
是 Dr.COM 本校:直接 campus-auth init,填账号,login。外校:用 generic 起配置,改 base_url 与密钥/参数
像是 Dr.COM,证据不全 别急着配:F12 抓一次真登录请求核实参数名
是锐捷 / 深澜 本项目不覆盖,换对应工具
没认出来 可能不是网页认证:路由器自带页、802.1X 都长这样

退出码:0 命中、1 未命中、2 地址格式错、3 环境问题、4 探不到(多半不在校园网)。

安装

pip install campus-auth
pip install "campus-auth[keyring]"   # 可选:把密码交给系统钥匙串

默认无第三方运行时依赖,keyring 是唯一的可选 extra。Python ≥ 3.10。 想跟未发布的主干,也可以装 git:

pip install "campus-auth @ git+https://github.com/young-ski/campus-auth"

没有 pip 的机器用单文件:从 Releases 下 campus-auth.pyz,python campus-auth.pyz status。 同一个 Release 里带 SHA256SUMS,sha256sum -c SHA256SUMS 能先核对再跑。

配置

优先级:内置默认 < 配置文件 < 环境变量 < 命令行参数。配置文件依次找 --config → $CAMPUS_AUTH_CONFIG → ./campus-auth.toml → 系统配置目录。

adapter = "huuc"       # 换成你自己学校的适配层
account = "081456789"  # 学号,纯数字,别带 @ 后缀
password = ""          # 留空则读 $CAMPUS_AUTH_PASSWORD,再不行读系统钥匙串
operator = "none"      # none / cmcc / unicom / dx,宿舍才需要
base_url = ""          # 留空用适配层里的地址
verify_tls = false     # 校园门户基本是自签证书
timeout = 20
retries = 2
interval = 120

密码必须是纯 ASCII。 门户前端只按 charCode 逐字符取异或,中文密码发出去的密文和浏览器不一致; 写了非 ASCII 会直接以配置错(退出码 2)拦下来。学号、MAC 同理。

密码别写进仓库。 优先级从高到低:命令行 -p → $CAMPUS_AUTH_PASSWORD → 配置文件 → 系统钥匙串。 推荐钥匙串(Windows 凭据管理器 / macOS Keychain / Linux Secret Service):

campus-auth password          # 交互式输入;管道里则读一行
campus-auth password --show   # 只看有没有存
campus-auth password --forget # 删
campus-auth login --remember  # 或者登录成功时顺手存

没装 keyring 或后端不可用(headless Linux 常见)时自动退回配置文件/环境变量。

开机自启

campus-auth install --dry-run   # 先看它要写什么、跑什么
campus-auth install             # Windows: HKCU\...\Run + .cmd;Linux: systemd --user;macOS: LaunchAgent
campus-auth uninstall           # 停掉并删干净

setup 最后一步也会问要不要装,不用再跑一遍。

配置默认写到 %APPDATA%\campus-auth\config.toml(POSIX 是 ~/.config/campus-auth/config.toml), 删掉解压出来的文件夹不影响自启。配置、.url 与日志在 POSIX 下是 0600。

自启进程不继承你当前 shell 的环境变量,密码得放进钥匙串或配置文件,install 会提醒。 日志在系统 state 目录(Windows %LOCALAPPDATA%\campus-auth\watch.log),watch 自己按 1 MiB 轮转;三条实现都带自动重启,崩了会自己回来。

JSON 输出

--json 时 stdout 只有 JSON 对象,提示、进度、服务端原文这类人话一律进 stderr, 所以 | jq 能直接用。支持这件事的只有 probe/status/login/logout/unbind/check/watch; 其余命令不接受这个参数。

每个对象都带 "schema": 1,同一版本内只增字段、不删不改。 字段表、示例和稳定性约定在 docs/json.md,机器可读版在 docs/json.schema.json(CI 会拿真实输出对一遍)。

命令与退出码

命令 作用
setup 首次配置一条龙:填学号、存密码、当场验一次、可选自启(--force 重来)
probe 探测门户类型,不需要账号(--url 给地址)
init 生成配置模板(--force 覆盖)
adapters 列出内置适配层与验证状态
login / logout / unbind 登录 / 注销 / 解除 MAC 绑定
status 列出门户会话,标出哪条是你自己的;online 指你自己、any_online 指门户里有任何会话
check 只判定在线与否,结果走退出码
doctor 体检:版本 / 配置路径 / 适配层 / 连通性 / 探测结论,密码只报来源
watch 保活循环,启动打摘要、每轮带耗时;--once 跑一轮,--log 同时落盘(自动轮转)
install / uninstall 把 watch 装成登录自启 / 卸掉(--dry-run 只打印)
password 密码存进/删出系统钥匙串(--show 看状态,--forget 删)
urls 按当前 IP 生成 .url / .desktop 快捷方式(内含可还原的密码)
退出码 含义
0 成功
1 认证被拒 / 未在线
2 配置问题(缺字段、适配层不存在、URL 写错)
3 环境问题(不在校园网、取不到本机 IP)
4 传输问题(超时、连接被拒、重试耗尽)

加一所学校

先跑 campus-auth new-adapter <代号>:生成的骨架带必改清单,改完在 adapters/__init__.py 登记。手抄的模板是 generic。步骤和验收清单见 CONTRIBUTING.md,那里也写了哪些东西不能提交(真实学号、密码、MAC)。

不想改主仓,或还没准备 PR:--adapter 也能直接从自己的文件加载(路径.py:属性名, 文件里只要有一个 Adapter 实例)。它依赖内部接口,请锁版本;跑通了把一行补进 docs/schools.md,别人少走一遍。

campus-auth status --adapter ./my_school.py:ADAPTER --url http://10.0.0.9:8080

打成了包也可以 pip install,再把名字注册到 campus_auth.adapters 这个 entry point 组, --adapter <名字> 就能选到。entry point 等于执行已安装的代码,信任前提与 pip install 一样。

已知限制

  • 只覆盖 Dr.COM / eportal 的网页认证。锐捷、深澜、802.1X、专用客户端加密的学校都用不了。
  • probe 是判断“哪一家”,不是抓包级证据;判成“证据不全”时仍需人工核实。
  • TLS 默认不校验证书(校园门户清一色自签)。想校验就 --verify-tls,遇到自签会失败。
  • .url / .desktop 快捷方式里的密码是 IP 异或的密文,而 IP 就在同一个 URL 里 —— 等于明文,分享前留意。报错里的 URL 默认把密码打成 ab…yz,要原文加 --show-secrets。
  • state.json 只存学号、IP、会话索引,不含密码。本版其实没有 state.json(锐捷/深澜下线时一起 删了),也没有 schtasks 计划任务;Windows 自启走注册表 HKCU\...\Run。
  • 门户升级会改参数名,适配层跟着改;generic 就是为此留的。

变更历史见 CHANGELOG.md。

免责与风险(自担风险)

学校目前没有对第三方客户端出过明确规定,用不用由你判断,出了问题也由你自己承担。具体是:

  • 非官方项目,与河南城建学院、Dr.COM 均无关系,没有任何人背书。
  • 只做网页认证的登录/注销/保活,不改计费、不绕过运营商套餐限制,也不替你去办开通。
  • 门户改版、学校加二次校验、运营商换策略,都可能让它突然失效;失效期间可能拖慢你的上网。
  • 密码会经过:内存、系统钥匙串(若启用)、配置文件(若你写了明文)、.url 快捷方式(密文但可 还原)、watch.log 与报错里的密文。别把 campus-auth.toml 提交进公开仓库。
  • 账号被锁、流量异常扣费这类事,先找学校网络中心,本项目帮不上。

能接受再用。只想临时试一次就手动 campus-auth login,别装自启。

要发给别人的话,文案和反馈模板在 docs/outreach.md。

漏洞与凭据相关的报告走 SECURITY.md 的私下通道;协议来自公开前端代码和本机抓包, 不含校内凭据。

许可证

MIT。

Metadata

Release files for campus-auth 1.7.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for campus-auth 1.7.5
File Size Uploaded Provenance Actions
campus_auth-1.7.5.tar.gz 116.2 kB With provenance Details for campus_auth-1.7.5.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for campus-auth 1.7.5
File Interpreter ABI Platform Actions
campus_auth-1.7.5-py3-none-any.whl Python 3 none any Details for campus_auth-1.7.5-py3-none-any.whl

Total release size: 203.9 kB

Release files / campus_auth-1.7.5.tar.gz

Download URL campus_auth-1.7.5.tar.gz
Size 116.2 kB
Tags Source
SHA-256 checksum
How to use checksums
30ddc4c3875676ad912ae54c0cde0ea2d13be31fd40eca21fd726eb095a20069
BLAKE2b-256 checksum
How to use checksums
5bb1c38005f6b48c7bce6e71e9a215b170f0e7736d47208cd4b1a8df23efefe7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 12, 2026.

Transparency log

Release files / campus_auth-1.7.5-py3-none-any.whl

Download URL campus_auth-1.7.5-py3-none-any.whl
Size 87.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4ad3a3e750715587d76cc8876913e3002a23c72e2a49b42e32ff10ff769db4e0
BLAKE2b-256 checksum
How to use checksums
aed55f24411d6f8a9ac4e4e80c7e58328fe6ad91977baed8ced2f80b2a2beb6c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 12, 2026.

Transparency log

Security for campus-auth 1.7.5

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for campus_auth-1.7.5.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 12, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page