关于湖南大学教务系统的研究#1

    科技2022-07-16  159

    前言

    前几天有个朋友和我抱怨小米的超级课程表(是叫这个?)不能很好的识别湖南大学的课程表,正好我也觉得湖大微生活受限于微信小程序,功能不足,所以我打算趁着十一假期研究一下湖南大学的教务系统,看看能不能整出什么花活。

    目前正在做的是一个PC/Android的跨平台课程表,用Qt和Boost。将来我看看能不能趁着选课系统开放的时候研究一下怎么选课,毕竟湖大的选课系统实在是太那啥了,每次十二点半开放,一点才选的上去,只能捡漏。

    话不多说,我们开始吧!这里我介绍一下从湖大教务系统获取课表的步骤,需要发送和接受的http包,和需要保存/发送的cookie等信息。

    下面提供的信息仅供学习用途,如果您想从湖南大学的教务系统/个人门户获取信息,请通过正常途径获取!


    得到请求课表的经过

    先讲一下我是怎么得到请求课表的步骤的。

    我们单刀直入,打开抓包软件,从“我的选课-课表查看”栏打开课表。待课表显示后,检查所有的Content-Type为application/json的返回包,发现有一个包包含了课表。找到请求这个包的request包。

    这个包是POST包,Content-Type也是application/json。

    我们检查一下这个包的具体内容,发现有作用的有这几项:

    TOKENCookie,包含authcode和SESSION包体

    我的包体是这样的: 显然,这个包体用来请求特定学期的课表。

    松了口气,搞定包体没有困难,我们来看看TOKEN和cookie怎么来的。

    在点击“课表查看”到课表显示之间抓取的http包中,查找值为TOKEN的值和SESSION的值的字符串,发现第一个包含TOKEN和SESSION的请求的包是一个GET请求。这证明TOKEN和SESSION在登陆的过程中已经生成。

    于是我们抓取开始登录个人门户到教务系统完全加载之间的http包。

    注意,这里登录个人门户使用的是https://pt.hnu.edu.cn/zfca?yhlx=student&login=0122579031373493685&url=login.aspx,是pt.hnu.edu.cn提供的可以直接重定向到教务系统的登录窗口。

    我们在所有的包中搜索SESSION的值,发现第一个包含SESSION的值是一个Response包,这个包通过Set-Cookie设定了token、authcode和SESSION 这几个值恰好就是我们请求课表所需要的cookie和TOKEN。

    找到请求这个包的request包。这个包是一个POST,请求的uri是/Njw2017/index.html,Content-Type是application/x-www-form-urlencoded。

    让我们看看它的包体…… 嗯,包含了学号、密码、不晓得的s_ticket……

    等一下,这个好像是明文的http包??虽然我们的个人门户登录入口受SSL保护,但是登录后再把学号密码用明文发一下真的行吗?

    好了,分析了这个非常危险的POST包,咱们看看s_ticket怎么拿到吧。

    我刚才也提到,我们的登录窗口受SSL保护,我提供的url也是https起头,那我们就分析一下https包。

    搜索“s_ticket”,发现第一个包含这个字符串的包是一个Response,其中的起重定向作用的location字符串指示了s_ticket,我们寻找请求到这个包的request。

    这个request是一个受SSL保护的POST包,Content-Type是application/x-www-form-urlencoded,有用的值是uri、cookie和它的包体。uri包含了一个jsessionid,cookie包含了一个JSESSIONID,包体包含了一个表单数据,表单数据中有用的是学号、密码、lt、_eventId和submit1。_eventId固定为"submit",submit固定为“登录”的百分号编码形式。jsessionid和JSESSIONID不同。

    我们先看看lt怎么来:

    经查找,发现lt实际上是登陆页面其中一个name为lt的控件的value。这个页面由一个GET包请求而来,这个GET包需要JSESSIONID。

    然后看看JSESSIONID怎么来:

    我们发现,在点击登录后,含JSESSION的包是一个request包,所以我们清除所有的cookie,分析从输入url之前到进入教务系统后的所有http和https包。发现第一个含JSESSIONID的包同时也是包含登陆页面的包,请求这个包的request包是一个GET包,不含任何可能变化的值。

    那jsessionid呢?

    我们发现,如果在加载登陆页面前没有任何cookie,那么jsessionid就和JSESSIONID一致。

    大功告成!已经发现了完整的请求课表的步骤!


    过程总结

    我们总结一下:

    SSL 发一个GET包,uri为/zfca/login?yhlx=student&login=0122579031373493685&url=login.aspx HTTP/1.1

    SSL 从返回包中获得JSESSIONID和lt

    SSL 发一个POST包,使用了jsessionid、JSESSIONID、lt、submit1、_eventId、学号、密码

    SSL 从返回包的location获得s_ticket

    发一个POST包,使用了学号、密码、s_ticket

    从返回的包中获得token、SESSION

    发一个POST包,使用TOKEN,SESSION,authcode,包体为一个json,包含了请求的学期等信息

    分析返回的json

    想偷懒、不想碰SSL可以用Qt的qWebEngineView控件,用js填写并发送表单,获取cookies等。


    后话

    以上就是我总结的请求湖大课表的信息,希望能帮助到各位。

    接下来我会继续这个Qt+Boost课程表的小项目,完成后我会把这个项目简要的介绍给大家,分享我封装的一些“脚手架”。

    我这里还有一些其他的小项目,包括已经完成的明日方舟自动刷图软件,正在开发的可编程配置文件和一个小的http server。时机成熟我也会把这些分享给大家。

    个人B站号:@染色XYX

    Processed: 0.008, SQL: 8