ujsAutoClock 江苏大学自动健康打卡项目(Chrome 扩展 & Android APP)

  • 设置简单,通知推送,QQ 接龙,熄屏运行(不同系统环境、Chrome 版本可能不一定有效)(妈妈再也不用担心没打卡啦
  • Chrome 扩展项目地址:https://github.com/tagbug/ujsAutoClock
  • Android 项目地址:https://github.com/tagbug/ujsAutoClock.apk

# 食用方法


下面是 Chrome 扩展的使用说明,Android 版本直接下载就行了,应该不用说明了

  • 1. 在 Github 上下载扩展

  • 2. 打开 Chrome 扩展程序的开发者模式
    在最右上角

  • 3. 选择 加载已解压的扩展程序

  • 4. 选择 ujsAutoClock 文件夹

  • 5. 允许 Chrome 在后台运行(占用系统资源很小)
    在设置->高级->系统里可以找到

  • 6. 首次安装会自动弹出设置页,填写好配置后保存,就可以自动运行了

  • 7. 如果想测试打卡效果直接在 Chrome 地址栏旁边的扩展程序里点击扩展图标

也可以在这里快速更改信息

  • 8. 最新版增加 QQ 群自动接龙功能,接龙是接群的第一个,因为有 QQ 密码这种敏感信息,需要右键扩展,在选项中配置

就是这里

  • 附。在 Chrome 扩展程序页选择选择 ujs自动健康打卡 -> 查看视图 背景页 可以在 Console 里看到自动打卡记录。

使用截图:

# 开发思路


# Chrome 扩展

其实一开始,我是拒绝的,一是因为写代码麻烦,二是因为觉得不重要,每天手动打卡就顺手的事,然而我错了,对于尤其像我这种昼夜时差颠倒的人,一不小心就会忘记,然后被打电话,所以…╮( ̄▽ ̄")╭

# 登录认证

  1. 打卡界面本来是在微信上的,选择 在浏览器打开 会得到一个打卡网址 serviceUrl="http://yun.ujs.edu.cn/xxhgl/yqsb/index" ,很显然需要用户认证,通过 "https://pass.ujs.edu.cn/cas/login?service="+serviceUrl 进行统一身份认证,浏览器会自动保存 Cookie(或者直接 "https://pass.ujs.edu.cn/cas/login" 好像也可以,这个参数的作用好像不是很明显,我没深究)
  2. 对登陆页的 form.submit 进行分析,可知 POST 有以下参数: username | password | captchaResponse | lt | dllt | execution | _eventId | rmShown
  3. 后面五个参数都是隐藏在 form 表单中,每次请求内容好像都没变过,前三个参数都是需要用户填写的,其中 password 字段在 POST 提交时还会被用 AES 加密(AES 用到的密钥也放在了表单中,每次请求都会改变)
  4. 知道了这些后,就可以写登录认证方法了,前面两个参数用户提供,每次不变,后面五个参数直接从 document 中提取,唯一比较棘手的就是验证码的处理,验证码每次从 'https://pass.ujs.edu.cn/cas/captcha.html?ts=' + new Date().getMilliseconds() 中随机生成
  5. 想到可以用 OCR 识别,在网上找了很多 OCR 的 API,要么是要钱,要么是效果不好,还好知道一个效果不错的免费 OCR,但是却没有开放的 API 接口,无奈只好自己扒
  6. 其实扒这个 OCR 的接口才是最耗时间精力的,中间踩了不少坑,反复用浏览器 F12 下断点调试 + BurpSuite 抓包,最后总算也是解决了,太过冗长也就不细讲了(其实这里用图像处理来对付验证码也可以,但是对于 JS 来说显然调 API 更省力)
  7. 到这里终于是可以写自动化脚本把这个流程串联起来了(访问 https://pass.ujs.edu.cn/cas/login 获取表单参数 -> 访问 'https://pass.ujs.edu.cn/cas/captcha.html?ts=' + new Date().getMilliseconds() 获取验证码图片信息 -> 丢给 OCR 处理 -> 返回验证码后把表单参数接起来 ->POST 获取返回数据 -> 检查登录状态是否成功(因为 OCR 有一定几率识别有误差,如果是验证码错误就重试,如果用户名密码错误直接结束,其他错误抛出异常))

# 定时打卡任务

  1. 在登录认证后直接访问 'http://yun.ujs.edu.cn/xxhgl/yqsb/grmrsb?v=' + parseInt(Math.random() * 10000) 就可以看到保存的打卡表单信息,注意到只有 下午温度上午温度其他异常 三个字段每天刷新,需要填写,这里用 Chrome 扩展强大的脚本插入功能,在页面加载完成后自动填写空缺字段提交,并返回提交结果
  2. 最后实现每天定时执行,用 Chrome 扩展的消息通信功能协调各个子模块的运行,用 chrome.storage.local 储存 用户名密码每日自动执行时间 ,用 chrome.notifications 实现桌面通知, popup.htmloptions.html 实现设置的读取和保存,方便用户操作

# Android 应用

这个是后来开发的,因为吧,虽然 Chrome 扩展开发起来简单,但最大的不足之处就在于无法同步通知到手机上,本来是想用发邮件的方式,找了很久也没发现什么用 JS 实现起来较为简单的方案,然后呢,我想着干脆直接在手机上开发一个应用,这样不就方便多了,而且实现原理都差不多… 嗯,原理是差不多,细节就差远了,本来以为一两天就能写完,最后边学边写写了四五天…

# 基本逻辑

  1. Get 登录页 -> 拿到一部分 Post 表单数据 ->Get 验证码 -> 用 OCR 读取 -> 整合表单 Post 登录 ->Get 打卡表单 -> 填补空缺项后 Post 打卡

# 细节

  1. 整个流程都是需要 HTTP 协议来进行数据交换的,原生的 Java HTTP API 效率太低了,用了开源软件 OkHttp,而且还需要实现 Cookie 的存储、更新和提交,Chrome 中浏览器就已经做好了这些,而在 Java 中只能自己来处理
    解决方法:实现 OkHttp 中的 CookieJar 接口来自动处理 Cookie(缓存、读取、过期更新、本地化)
    这里参考了:OkHttp 官方文档 OkHttp3 实现 Cookies 管理及持久化

  2. 然后第二个就是 Android 应用运行机制,包括应用组件:Activity、Service、BroadcastReceiver 和 ContentProvider(虽然我只用到了第一个和第三个…),清单文件,应用资源(布局、图标等),Intent、Context、Bundle…
    不得不说,相当复杂…(关键是官方 API 文档还全是英文,看都看不懂)

  3. 第三个是用闹钟 AlarmManager 实现定时执行任务(这个东西是真迷幻,不知道为什么定时总会有几分钟偏差)(用 setExactAndAllowWhileIdle 方法即可准时广播)

  4. 最后用 Notification 推送通知(这个东西也是,不同的 API 所要求的实现方法有细微区别,不注意就会导致通知推送不出来,找半天都不知道是哪的问题…)

  5. Android 系统的开放性、既要兼顾不同的 Android 系统版本(从高到低的 SDK 版本)、又因为各种厂商对自家手机系统的魔改,导致 Android 开发是个相当不容易的工作… 很佩服

参考:
Chrome 插件 (扩展) 开发全攻略
Android 开发者