四川大学新教务处系统选课分析

川大在暑假的时候更新了教务处系统,昨天第一次上线使用。

登录

登录的流程没变,都是请求JSESSIONID,之后所有操作都是通过JSESSIONID进行身份验证。
首先发送

1
2
3
4
5
6
7
8
GET /login HTTP/1.1
Host: 202.115.47.141
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close

Respose含有set-Cookie, set-Cookie包含JSESSIONID。

再发送请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
POST /j_spring_security_check HTTP/1.1
Host: 202.115.47.141
Content-Length: 59
Cache-Control: max-age=0
Origin: http://202.115.47.141
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: http://202.115.47.141/login
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: JSESSIONID=bcdccjiHgvOhY-wExDuyw
Connection: close

j_username=20171414*****&j_password=******&j_captcha1=error

参数名 说明
j_username 用户名
j_password 密码
j_captcha1 固定为“error”,暂时还不知道为什么

如果登录成功则,返回的Response为

1
2
3
4
5
6
7
8
HTTP/1.1 302 Found
Server: Resin/3.0.27
Location: http://202.115.47.141/index.jsp
Content-Length: 69
Connection: close
Date: Wed, 26 Sep 2018 05:51:49 GMT

The URL has moved <a href="http://202.115.47.141/index.jsp">here</a>

到此登录成功!

选课

发送请求

1
2
3
4
5
6
7
8
9
10
GET /student/courseSelect/courseSelect/index HTTP/1.1
Host: 202.115.47.141
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: http://202.115.47.141/index.jsp
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: JSESSIONID=bacqKjIdZIeKs7fAUBuyw; selectionBar=1293218
Connection: close

JSESSIONID即为刚刚登录使用的JSESSIONID,而selectionBar经试验无太大关系。

在Response内得到fajhh参数 fajhh为培养方案的代码

发送请求

1
2
3
4
5
6
7
8
9
10
GET /student/courseSelect/freeCourse/index?fajhh=**** HTTP/1.1
Host: 202.115.47.141
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: http://202.115.47.141/student/courseSelect/courseSelect/index
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: JSESSIONID=bacqKjIdZIeKs7fAUBuyw; selectionBar=1293218
Connection: close

在Response内,我们找到

然后随便选一门课,,发现其POST的内容与以上极其吻合,POST地址也为以上地址。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
POST /student/courseSelect/freeCourse/waitingfor?dealType=3 HTTP/1.1
Host: 202.115.47.141
Content-Length: 167
Cache-Control: max-age=0
Origin: http://202.115.47.141
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: http://202.115.47.141/student/courseSelect/freeCourse/index?fajhh=3541
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: JSESSIONID=bacqKjIdZIeKs7fAUBuyw; selectionBar=1293218
Connection: close

tokenValue=5733e54838faa3561cb7083d85cb0915&kcIds=104215020_01_2018-2019-1-1&kcms=%E5%A4%A7%E4%BC%97%E4%BC%A0%E6%92%AD%E5%AD%A6_01&fajhh=3541&sj=2_10&searchtj=&kclbdm=

参数名 说明
tokenValue 为之前获取的内容
kcIds 课程号课序号学期号
kcms 课程名称的URL编码_课序号
fajhh 之前获取到的培养方案号
sj 上课的时间如2_10即为周二第10节课,但是直接设为0_0也是可以通过的
searchtj
kclbdm

如果tokenValue不对,就直接跳向logout。这就是为什么昨天上午很多同学在选课之后就直接返回了登录界面。

在Response内找到以下js代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
var kcNum = "1";
var redisKey = "20171414*****3";
var kcIds = "104215020_01_2018-2019-1-1";
var kcms = "大众传播学_01";
var intervalf = 0;
var times = 0;
$(function(){
var resCont = "<tr><th>课程名</th><th>选课结果</th></tr>";
if(kcIds!="" || kcms!=""){
var kcIdArr = kcIds.split(",");
var kcmArr = kcms.split(",");
for(var i=0;i<kcIdArr.length;i++){
var ids = kcIdArr[i].split("_");
resCont += "<tr><td width='35%' align='right'>"+kcmArr[i]+"</td><td id='"+ids[0]+"_"+ids[1]+"'></td></tr>";
}
}
$("#xkresult").html(resCont);
getXkResult();
intervalf = setInterval(getXkResult,3000);
});
function getXkResult(){
times++;
$("#xkMsg").html("第"+times+"次获取选课结果...");
$.ajax({
url:"/student/courseSelect/selectResult/query",
method:"post",
data:"kcNum="+kcNum+"&redisKey="+redisKey,
dataType:"json",
success:function(data){
if(data["isFinish"]){
window.clearInterval(intervalf);
$("#tip").hide();
$.each(data["result"],function(i,it){
var resC;
var keyval = it.split(":");
if(keyval[1]=="选课成功!"){
//urp.alert("选课成功必须选教材!");
resC = "<span class='badge badge-success'>"+keyval[1];
if(data["schoolId"]=="100010"){
resC +="<a href='/student/courseSelect/books/dealBooks/index'>去选教材</a>";
}
resC +="</span>";
}else{
resC = "<span class='badge badge-danger'>"+keyval[1]+"</span>";
}
$("#"+keyval[0]).html(resC);
});
}
},
error:function(){
urp.alert("查询选课结果出错!");
}
});
if(times==10){
window.clearInterval(intervalf);
$("#reget").removeClass("disabled");
urp.alert("当前排队人数过多,暂未获得选课结果(不表示你未选中此门课程)。<br>请稍后从“选课结果”中查看结果。");
}
}
function getAgein() {
$("#reget").addClass("disabled");
times = 0;
getXkResult();
intervalf = setInterval(getXkResult,3000);
}

这就是这个系统最鸡肋的地方了。每隔3秒发送一次POST请求,查看选课是否成功,当查询到选课成功或发送10次,即停止。
为什么这样很鸡肋呢?
如果人少的时候,POST一次就够了。
如果人多的时候,再怎么POST都返回不了结果的,所以每次选课都会POST10次,这就是新版系统智障的地方了,选完一次课,D自己10次(和某isdc副会写的孔豪加加加一样)。如果选课的人一多,只会造成越来越卡。
发送请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
POST /student/courseSelect/selectResult/query HTTP/1.1
Host: 202.115.47.141
Content-Length: 31
Accept: application/json, text/javascript, */*; q=0.01
Origin: http://202.115.47.141
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://202.115.47.141/student/courseSelect/schoolCourse/waitingfor?dealType=3
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: JSESSIONID=bacqKjIdZIeKs7fAUBuyw; selectionBar=1293218
Connection: close

kcNum=1&redisKey=20171414*****3

如果选课成功,则返回值为

至此,一次正常的选课流程结束。

脚本

获取JSESSIONID

发送请求

1
2
3
4
5
6
7
8
GET /login HTTP/1.1
Host: 202.115.47.141
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close

在Response内得到

JSESSIONID=bcdccjiHgvOhY-wExDuyw

登录

发送请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
POST /j_spring_security_check HTTP/1.1
Host: 202.115.47.141
Content-Length: 59
Cache-Control: max-age=0
Origin: http://202.115.47.141
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: http://202.115.47.141/login
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: JSESSIONID=bacqKjIdZIeKs7fAUBuyw
Connection: close

j_username=20171414*****&j_password=******&j_captcha1=error

参数名 说明
j_username 用户名
j_password 密码
j_captcha1 固定为“error”,暂时还不知道为什么

如果登录成功则,返回的Response为

1
2
3
4
5
6
7
8
HTTP/1.1 302 Found
Server: Resin/3.0.27
Location: http://202.115.47.141/index.jsp
Content-Length: 69
Connection: close
Date: Wed, 26 Sep 2018 05:51:49 GMT

The URL has moved <a href="http://202.115.47.141/index.jsp">here</a>

获取fajhh

发送请求

1
2
3
4
5
6
7
8
9
10
GET /student/courseSelect/courseSelect/index HTTP/1.1
Host: 202.115.47.141
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: http://202.115.47.141/index.jsp
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: JSESSIONID=bacqKjIdZIeKs7fAUBuyw; selectionBar=1293218
Connection: close

在Response内得到fajhh

获取tokenValue

发送请求

1
2
3
4
5
6
7
8
9
10
GET /student/courseSelect/freeCourse/index?fajhh=3541 HTTP/1.1
Host: 202.115.47.141
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: http://202.115.47.141/student/courseSelect/courseSelect/index
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: JSESSIONID=bacqKjIdZIeKs7fAUBuyw; selectionBar=1293218
Connection: close

url的fajhh参数即为之前获取的参数
在Response内得到tokenValue与dealType

选课请求

发送请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
POST /student/courseSelect/freeCourse/waitingfor?dealType=3 HTTP/1.1
Host: 202.115.47.141
Content-Length: 167
Cache-Control: max-age=0
Origin: http://202.115.47.141
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: http://202.115.47.141/student/courseSelect/schoolCourse/index?fajhh=3541
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: JSESSIONID=bacqKjIdZIeKs7fAUBuyw; selectionBar=1293218
Connection: close

tokenValue=5733e54838faa3561cb7083d85cb0915&kcIds=104215020_01_2018-2019-1-1&kcms=%E5%A4%A7%E4%BC%97%E4%BC%A0%E6%92%AD%E5%AD%A6_01&fajhh=****&sj=2_10&searchtj=&kclbdm=

此处的参数见上,url的dealType参数也是在前一个步骤获取的
在Response的js代码块内得到参数KcNum与redisKey

查询选课结果

发送请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
POST /student/courseSelect/selectResult/query HTTP/1.1
Host: 202.115.47.141
Content-Length: 31
Accept: application/json, text/javascript, */*; q=0.01
Origin: http://202.115.47.141
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://202.115.47.141/student/courseSelect/schoolCourse/waitingfor?dealType=3
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: JSESSIONID=bacqKjIdZIeKs7fAUBuyw; selectionBar=1293218
Connection: close

kcNum=1&redisKey=20171414*****3

查询选课结果。

脚本流程

文章目录
  1. 1. 登录
  2. 2. 选课
  3. 3. 脚本
    1. 3.1. 获取JSESSIONID
    2. 3.2. 登录
    3. 3.3. 获取fajhh
    4. 3.4. 获取tokenValue
    5. 3.5. 选课请求
    6. 3.6. 查询选课结果
    7. 3.7. 脚本流程