本文仅供技术学习与交流,请勿用于违反校规校纪的行为。

前言

学校使用的智慧学工考勤系统要求学生在指定时间、指定地点进行 GPS 打卡签到。出于对移动端安全和 Web 接口逆向的学习兴趣,我对该系统的签到流程进行了分析,并编写了一个 Android 应用来复现整个过程。

系统分析

签到流程拆解

通过抓包分析,整个考勤签到系统的核心流程如下:

登录认证 → 获取课程列表 → 获取打卡任务 → 提交签到(经纬度 + 精度)

GPS 定位验证机制

系统前端使用了一个 geoDistance2Ranges 函数,基于 GCJ-02 坐标系计算用户位置与目标点之间的距离。关键发现:

  • 定位验证仅在客户端(JavaScript)执行,服务端并不会二次校验 GPS 坐标的合理性
  • 签到接口直接接收客户端 POST 的 latitudelongitudeaccuracy 参数
  • 照片字段(photo)同样不做强制校验

这意味着只要构造合法的 HTTP 请求,就可以提交任意坐标完成签到。

登录认证流程

登录并非简单的账号密码验证,而是一套与微信绑定的多步骤流程:

1. POST 姓名 + 学号 + 验证码 → 返回中间页(stop page)
2. 从中间页提取微信扫码登录链接
3. 用户在微信中打开链接完成授权
4. 轮询检测登录状态 → 获取重定向 URL
5. 跟随重定向拿到最终 Session Cookie

其中有个坑:服务端返回的重定向 URL 是 JSON 格式,其中 / 被转义为 \/,直接使用会导致路径出现双斜杠 //,需要手动 unescape。

技术实现

技术栈

组件技术选型
语言Kotlin
网络请求OkHttp3 + 自定义 CookieJar
HTML 解析Jsoup
UI 框架Material Design 3
本地存储SharedPreferences
异步处理Kotlin Coroutines

核心模块

PunchApi.kt — 网络层封装

负责所有与服务端的交互,包括:

  • Session 管理:自定义 CookieJar 跨域持久化 Cookie
  • 登录流程:处理验证码获取、表单提交、微信 QR 链接提取、登录状态轮询
  • 签到提交:构造 POST 请求发送自定义经纬度

为了绕过服务端的 UA 检测,请求头模拟了完整的浏览器指纹(User-Agent、Referer、Origin 等)。

MainActivity.kt — UI 与业务逻辑

采用单 Activity 多 View 的架构,通过控制 loginViewguideViewmainContent 三个视图的显隐来实现页面切换:

  • 登录页:输入姓名、学号、验证码
  • 引导页:展示微信登录链接,提供一键复制功能,实时显示轮询状态
  • 主页面:GPS 坐标设置、预设管理、课程打卡列表、签到历史

PrefsManager.kt — 本地持久化

使用 SharedPreferences 存储:

  • 登录凭证(Cookie),实现免登录
  • GPS 预设位置列表
  • 签到历史记录

关键代码片段

签到请求的核心就这几行:

val formBody = FormBody.Builder()
    .add("latitude", lat.toString())
    .add("longitude", lng.toString())
    .add("accuracy", "65.0")
    .add("photo", "")
    .build()

val request = Request.Builder()
    .url("$BASE_URL/student/course/$courseId/punch/$punchId")
    .header("User-Agent", UA)
    .post(formBody)
    .build()

服务端只看这几个字段,没有任何额外的签名或设备指纹校验。

功能一览

  • 学生身份登录(姓名 + 学号 + 验证码)
  • 微信扫码授权登录
  • 登录状态持久化,下次打开免登录
  • 自定义 GPS 经纬度进行签到
  • GPS 预设位置管理(添加 / 删除 / 快速切换)
  • 课程列表与打卡任务查看
  • 签到历史记录本地保存
  • 退出登录

安全声明

本应用:

  • 未接入任何第三方 SDK 或接口
  • 未收集、上传、存储用户的任何个人信息
  • 所有数据仅在用户设备本地保存
  • 仅与以下两个域名通信:

    • https://wx703c2206450720dd.g8n.cn(考勤系统)
    • https://login.b8n.cn(登录认证)

源码

仓库地址(私有):http://43.136.67.174:9999/aven/GPSPunchApp

写在最后

这个项目的目的是学习移动端逆向和 Web 接口分析,整个过程涉及到了抓包分析、Cookie 会话管理、HTML 解析、多步骤登录流程处理等实用技术。

从安全角度来看,该考勤系统存在明显的设计缺陷 — 将关键校验逻辑放在客户端而非服务端。对于开发者而言,这是一个很好的反面教材:永远不要信任客户端提交的数据


开发者:凡笙

最后修改:2026 年 03 月 14 日
如果觉得我的文章对你有用,请随意赞赏