新版正方教务系统登录实现
最近开学后相信很多同学都发现课表小程序等无法使用了,这是因为学校更新了正方教务系统,导致了大批基于旧版正方系统的校园小程序无法继续爬取课表。
之前曾在GitHub上看到过本校师兄开发的school-api
–一个基于旧版正方的python SDK,但新版无法使用。因此花了两天时间研究了下新版正方的登录(能登录后续的就EZ啦~)
既然都弄了,因此计划开发一个新的SDK。我比较懒 暂命名为new-school-sdk
,项目目前还在开发中,先将登录的流程、验证码识别的思路罗列出来。(拿到了cookies 还有啥不能干嘛)
项目Github地址: https://github.com/Farmer-chong/new-school-sdk
登录前期准备
通过观察发现,有以下几个难点:
- 新版正方使用Java进行开发且并非前后端分离,因此只要我们能拿到
cookie
即能完成登录。 - 验证码的识别
- 正方使用了Rsa对数据进行加密
针对上述问题,开始一一解决
验证码部分
前置工作准备好后,开始从服务器获取验证码并进行验证
获取验证码
网络抓包发现,验证码是异步获取的,每次刷新都会发送一个请求到/zfcaptchaLogin
请求报文内容有:
1 | "type": "refresh" |
响应报文内容:
1 | imtk: "29730cb5-d7ff-4fc9-aa9d-e3efc0a07f55" |
观察请求报文发现需要type
、rtk
、time
和instanceId
这几个字段。
其中rtk
未知,因此开始寻找其出现的地方。通过查找发现rtk出现在一个js文件中,初步猜测rtk
是一个令牌,由服务器随机生成的。
因此我们要先获取rtk
令牌,然后利用正则表达式将其值提取出来。
下载验证图片
但现在仍然无法获取验证图片的原始数据,再观察img
的src
属性,得知响应报文中的mi
和si
分别别是验证码
和滑块
。并且需要的url参数我们也已经获取了。
向/zfcaptchaLogin
发送一个GET
请求,请求参数如下:
1 | type: image |
滑动验证码识别
上文中有提到,参考这篇文章: https://blog.dairoot.cn/2021/06/26/zf-sliding-captcha/
大致流程如下:
- 将图片灰度化
- 识别出一段颜色差小于阈值的线(竖的)
- 识别出来的这段线不能太短(要和缺口差不多高)
因此即可计算出该线的x轴坐标,因此得到滑块偏移量。
模拟人手拖动&发起验证请求
从上一步中,我们得到了偏移量X
和Y
,接下来就要开始模拟人手拖动滑块的过程了。人手滑动验证码时,一般都是先快后慢的一个速度曲线,因此利用物理学公式分段设置加速度a
,前半段a > 0
,后半段a < 0
。
当前速度用v
表示,初速度用v0
,位移用x
,时间用t
,它们之间满足如下关系:x = v0 * t + 0.5 * a * t^2
v = v0 + a * t
移动算法的代码实现如下:
1 | def _get_track(self, distance, y): |
至此,我们得到了发起请求的所有数据,因此向/zfcaptchaLogin
发送一个POST
请求,请求体如下:
1 | type: verify |
当验证通过时,得到如下的响应体:
1 | msg: "" |
登录部分
获取RSA公钥
通过查看页面源码和点击登录后抓包,登录发送一个请求到/xtgl/login_slogin.html
,然后返回一个302的跳转。
其中请求报文内容如下:
1 | csrftoken: csrftoken |
此处csrftoken
和mm
两个字段是未知的。其中csrf
令牌是为了防止攻击的,一般包含在form
表单中,由后端生成。因此我们可以直接从页面中提取。如下图:
而mm
字段,通过对前端异步请求部分的代码进行分析后,发现是利用RSA
进行加密,从抓包中可以发现一个发送到/login_getPublicKey.html
地址的GET
请求。其响应体内容如下:
1 | exponent: "AQAB" |
因此得到了RSA
的指数
和模
,但这里的modulus
长度为 172。大概率是正方修改过加密,在JavaScript
文件的注释中也可以看到。
本来是打算自己重写一个python版的实现,后来在GitHub
上发现已有前人栽树,我乘凉就好啦!
到现在为止,整个登录流程的未知项就全解决了!🛫🍯
开始登录
再次观察数据包的流程,得知登录各项的顺序并做优化:
! 注意,在登录发生302跳转的时候,cookie会发生改变 !
- 访问登录页面,获取
csrf
和原始的cookies
- 获取
rsa
公钥 - 处理滑块验证
- 发起登录,得到登录后的
cookie
成功截图:
后记
sdk开发中,希望大佬们多多给意见或者一起开发哈!