本文档只说明校园网登录与注销本身的 HTTP 落地逻辑,不讨论本项目的界面、托盘、更新、函数名或模块拆分。

1. 总体思路

这套校园网认证不是“直接提交账号密码然后等结果”这么简单,而是通常分成三步:

  1. 先请求状态接口,确认当前是否已经在线
  2. 如果在线,判断是不是当前账号在线,还是别的账号在线
  3. 再决定执行登录,还是先注销再登录,或者直接返回“无需重复登录”

当前落地里,状态检测、登录、注销这三类请求都使用 GET

2. 三类接口的默认地址

默认会使用两组地址:

  • 状态检测接口:http://10.2.5.251/drcom/chkstatus
  • 登录/注销接口:http://10.2.5.251:801/eportal/

也就是说,默认约定是:

  • chkstatus 走 80 端口
  • eportal 认证走 801 端口

如果学校环境修改了网关地址,本质上也还是这两类接口:

  • 一个用于查在线状态
  • 一个用于提交登录/注销动作

3. 为什么先查状态接口

状态接口不是辅助信息,而是整条认证链路的基础。

先查状态的原因有三个:

  • 判断当前网络是不是已经认证成功
  • 判断当前在线的是不是目标账号
  • 取出后续登录/注销要用的 wlan_user_ip

也就是说,登录和注销都依赖状态接口返回的 IP 信息,而不是随便取本机网卡 IP。

4. 状态检测接口的请求方式

状态检测走 GET

请求形式大致是:

GET http://10.2.5.251/drcom/chkstatus?callback=dr{timestamp}&v={random}

关键点:

  • callback=dr{timestamp}:这是一个 JSONP 回调名
  • v={random}:通常是一个随机数,用来尽量避免缓存

这里不是普通纯 JSON 接口,而是 JSONP 风格返回。

5. 状态检测接口的返回解析

返回内容通常长这样:

dr1743926400000({"result":1,"uid":"20230001@cmcc","v46ip":"10.x.x.x"})

解析逻辑很直接:

  1. 找到第一个 (
  2. 找到最后一个 )
  3. 取出中间的 JSON 字符串
  4. 再按 JSON 反序列化

解析后最关键的字段是:

  • result
    • 1 表示在线
    • 1 一般表示未认证
  • uid
    • 当前在线账号
  • v46ip
  • v4ip
  • ss5

IP 的提取顺序通常是:

v46ip -> v4ip -> ss5

谁先有值就用谁。

这个 IP 后面会继续用于:

  • 登录请求里的 wlan_user_ip
  • 注销请求里的 wlan_user_ip

6. 登录接口的请求方式

请求结构大致如下:

GET http://10.2.5.251:801/eportal/?c=Portal&a=login
  &callback=dr{timestamp}
  &login_method=1
  &user_account={account}
  &user_password={password}
  &wlan_user_ip={ip}
  &wlan_user_mac=000000000000
  &wlan_ac_ip=
  &wlan_ac_name=
  &jsVersion=3.0
  &_={timestamp}

其中最关键的参数是:

  • c=Portal
  • a=login
  • login_method=1
  • user_account
  • user_password
  • wlan_user_ip

7. 登录参数怎么拼

7.1 user_account

账号一般不是裸学号,而是:

学号@运营商

例如:

20230001@cmcc
20230001@unicom
20230001@telecom

如果是纯校园网、不带运营商后缀,则直接传学号本身。

7.2 user_password

密码放在查询参数里,因此必须做 URL 编码。

否则一旦密码里有这些字符,就会把整个查询串打坏:

  • &
  • +
  • %
  • =

所以正确做法不是“把密码原样拼上去”,而是先编码,再放进 URL。

7.3 wlan_user_ip

这个字段不建议自己猜,也不建议直接读本机网卡地址。

更稳妥的做法是:

  • 先从 chkstatus 返回里取
  • 优先取 v46ip
  • 再回退 v4ip
  • 再回退 ss5

因为校园网认证系统认的,往往是它自己状态接口里看到的在线 IP。

7.4 其他参数

  • callback=dr{timestamp}:用于 JSONP 风格返回
  • _={timestamp}:常见防缓存参数
  • wlan_user_mac=000000000000:当前实现里固定值
  • wlan_ac_ip=wlan_ac_name=:当前留空
  • jsVersion=3.0:按现网接口习惯保留

8. 登录前的实际判断逻辑

真正落地时,登录前一般先按下面顺序判断:

  1. 调状态接口
  2. 如果已经在线:
    • 如果在线账号就是目标账号,直接返回“已在线”
    • 如果在线账号是别的账号,先提示“是否顶号”
  3. 如果未在线:
    • 直接发登录请求

这意味着“顶号判断”本质上不是登录接口单独返回的概念,而是靠状态接口先发现“已有别的账号在线”。

9. 强制登录时为什么要先注销

如果确认要顶号,更稳妥的做法不是直接再次登录,而是:

  1. 先发注销请求
  2. 等注销成功
  3. 再发登录请求

这样能把“别的账号已在线”的状态先清掉,减少新登录被网关拒绝或状态异常的概率。

10. 注销接口的请求方式

当前校园网注销同样走 GET

请求结构大致如下:

GET http://10.2.5.251:801/eportal/?c=Portal&a=logout
  &callback=dr{timestamp}
  &login_method=1
  &user_account=drcom
  &user_password=123
  &ac_logout=0
  &wlan_user_ip={ip}
  &wlan_user_ipv6=
  &wlan_vlan_id=1
  &wlan_user_mac=000000000000
  &wlan_ac_ip=
  &wlan_ac_name=
  &jsVersion=3.0
  &_={timestamp}

这里最关键的是:

  • a=logout
  • wlan_user_ip

以及这组相对固定的参数:

  • user_account=drcom
  • user_password=123
  • ac_logout=0
  • wlan_vlan_id=1

这说明注销接口不是“把登录时那套账号密码重新传一遍”,而是按网关要求提交一组固定格式参数。

11. 登录/注销的成功判定

返回文本不一定总是统一格式,所以实际落地里更常见的是“启发式判定成功”。

一个常见做法是只要命中以下任一特征,就认为成功:

  • "result":"1"
  • "result":1
  • 成功
  • success

优点:

  • 对不同学校或不同版本网关的兼容性更强

缺点:

  • 不是严格协议校验
  • 如果网关返回格式变化很大,可能需要再补新的成功特征

12. 为什么这里没有 POST

就这套现网协议来说,当前落地使用的是:

  • 状态检测:GET
  • 登录:GET
  • 注销:GET

不是:

  • 状态检测 GET,登录 POST
  • 或登录/注销都 POST

所以如果后续要迁移到别的学校环境,首先要确认的不是账号格式,而是:

  • 它的登录接口到底是 GET 还是 POST
  • 参数是在 query string 里,还是 form body 里
  • 注销是不是也复用同一套入口

13. 异常处理的落地思路

协议层通常要区分两种失败:

13.1 请求根本没打通

这类问题包括:

  • 不在校园网环境
  • 校园网网关地址不通
  • 系统代理把请求带偏了
  • TUN 模式接管了流量
  • 超时

这种情况本质上不是“账号密码错”,而是“没有成功直连认证网关”。

13.2 请求打通了,但业务失败

这类问题包括:

  • 账号错误
  • 密码错误
  • 网关返回未成功状态
  • 当前已有别的账号在线

这两类问题要分开处理,否则用户会把“网络不通”误以为“密码错了”。

14. 一条完整的落地链路

如果把校园网认证逻辑抽象成协议层,完整流程可以概括成:

  1. GET /drcom/chkstatus
  2. 解析 JSONP
  3. 取出:
    • 是否在线
    • 当前在线账号
    • wlan_user_ip
  4. 如果已经是目标账号在线,直接结束
  5. 如果是别的账号在线,先询问是否顶号
  6. 若确认顶号,先 GET /eportal/?c=Portal&a=logout...
  7. GET /eportal/?c=Portal&a=login...
  8. 根据返回文本判断成功或失败

这就是当前校园网登录/注销最核心的协议落地逻辑。


K
ken · 全栈工程师

专注于 Node.js 生态、Linux 系统配置与数据库调优。记录折腾过的每一个坑,希望对你有帮助。