为提高阅读体验,本文分为上中下三篇。

想法来源

一直都很好奇《超级课程表》这款 App 是如何适配大部分高校获取其的课程表,简单查阅后,发现它是通过登录正方教务管理系统获取的课表。登录 http://es.bnuz.edu.cn 简单查看,发现它是直接返回渲染完成的课表页面,需通过正则匹配获取,太麻烦啦!!!

想起我们学校还有一个 TMS 教务管理系统 (http://tm.bnuz.edu.cn), 不如登录时抓包看看,说不定能找到有用的信息呢!

Let’s Start!

Chrome 登录 TMS 教务管理系统 (http://tm.bnuz.edu.cn)

登陆后先不点其他地方 Chrome 打开调试 - Network 在 Filter 旁边选择XHR,过滤出我们需要的信息:如下图

然后点击顶部导航栏-教学过程-我的课表,Network Tab 栏会出现一个名为schedules URL -Preview Amazing!这就是我的课表耶!这是个 JSON 数据包,返回的为登录学生的课表信息。

点击Headers - General - Request URL为: http://tm.bnuz.edu.cn/api/core/students/[StudentNum]/schedules 直接访问这个链接,就能获得自己的课表信息啦!

那么,如果把 StudentNum 换成别人的学号呢,能否得到别人的课表信息,尝试后发现是不可以滴!所以还会涉及到权限验证问题。

要获取指定学号的课表信息呢,就意味着要执行登录操作后才可以进行。

那么,尝试一下模拟登陆吧!

模拟登陆前分析

要进行模拟登陆,我们就要分析一下系统的登录过程。像上一步那样,Chrome 打开调试 - Network - 勾选 Preserve log

然后先在教务管理系统执行退出操作,退出后会自动跳转到 http://tm.bnuz.edu.cn/uaa/login ,为了避免本地 Cookies 对登录过程的影响,我们先清理一遍本地的 Cookies。

具体操作:

清理完后,再刷新当前页面,观察右侧 Network 栏,状态如下图所示:

可以看出,该登陆过程并不简单,进行了6 次的 302 重定向。

没有更好的办法(或者是我没找到),我们只能一步步分析啦。

Wikipedia:关于 302 重定向

截取一句话 : 服务器通常会给浏览器返回 HTTP Location 头部来重定向到新的新位置。

具体 302 重定向如下图:

点开第一个 login,分析了一下 Response Headers 响应头,返回有以下信息:

Headers 里面的 Location 字段,就是重定向的地址,同时服务器向我们的浏览器进行了 Set-Cookie 操作:

  • Set-Cookie: XSRF-TOKEN=5437d52a-a8b8-48bb-80e9-9b81e19842f7; Path=/
  • Set-Cookie: JSESSIONID=955D64D3E6FD6F6DBCEC3C93CBCB0FD8; Path=/; HttpOnly

其中 HttpOnly 表示的是该 Cookie 在客户端是无法通过 JS 读取的,(document.cookie 为空),加入该字段一般为了防止 XSS(Cross Site Script)跨站脚本攻击,关于 XSS 和 CSRF,我也是前些天才开始明白其中的原理,过些天再写一篇总结吧。

然后点开重定向到的第二个 URL:还是查看 HTTP Headers 信息,我们可以看到这次 Request Headers 请求头附带了很多信息:

其中关注下 Cookie 字段,我们发现这个的请求附带了上一歩服务器 Set-Cookie 的值。

接着我们按照同个思路继续分析下面几步,会发现每次的 302 重定向都是通过用上一步得到的 Cookie 值去换取新的 Cookie 值。

具体步骤如下:

  • ① 在 URL:http://tm.bnuz.edu.cn/login 取得XSRF-TOKEN以及JSESSIONID-A,重定向
  • ② 通过 ① 取得的XSRF-TOKEN以及JSESSIONID 换取UAA-XSRF-TOKEN-A和新的JSESSIONID-B,重定向
  • ③ 通过 ① 取得的XSRF-TOKEN以及 ② 取得的X-UAA-XSRF-TOKEN-A和新的JSESSIONID-B换取新的UAA-XSRF-TOKEN-B和新的JSESSIONID-C,并传入用户名密码进行验证。
  • ④ 验证成功后,服务器返回新的UAA-XSRF-TOKEN-C以及新的JSESSIONID-D,再次重定向
  • ⑤ 通过 ④ 取得的新的 Cookie,访问第 ④ 步取得的 URL,换取新的 Location 重定向地址 URL
  • ⑥ 使用 Cookie UAA-XSRF-TOKEN-CJSESSIONID-DJSESSIONID-CUAA-XSRF-TOKEN-B换取重定向地址
  • ⑦ 服务器返回 FINAL-XSRF-TOKENFINAL-JSESSIONID,至此,取得了可以访问 API 接口的 Cookie

为了方便区分各 Cookie 的值,我给它们作了 ABCD 的标记,以示区分。

分析完毕后,可能会觉得这步骤很繁琐,很乱,没关系,下一篇文章我们通过 Async 模块一步步完成。

结语

花那么多时间分析是因为 TMS 的 API 返回的信息直接就是 JSON 格式的,在使用起来确实比正方系统的方便很多。为了能成功进行模拟登陆,我们就必须要分析好每一步的过程。