注意:本文以湖南工程学院教务网络管理系统
(青果教务系统)为例,其他青果系统类似,本文只提供思路,不提供代码
u1s1,这是我爬过最有趣的网站了,过程曲折而有意思
第一部分:验证码及ASP.NET_SessionId的获取
这是学校教务网的首页,很明显,要登录的话至少需要账号,密码,验证码
很快就遇到了第一个难题——验证码的获取
通过分析前端代码,不难发现整个登录页面是个单独的iframe
而且验证码也不是什么好招呼的主,本来想着用请求直接将验证码保存下来,结果发现这个请求的header中有个Cookie
,里面有个ASP.NET_SessionId
,并且是个随机值
通过查阅资料,发现这是ASP.NET用来判断web会话状态的一个参数,只要访问过页面之后就会保存在cookies
中。那么问题就解决了,只要先请求一次教务网主页home.aspx
,然后就能从cookies
中找到这个值
SessionId = session_requests.cookies["ASP.NET_SessionId"]
注意:为了保持同一个会话,所有请求都必须带上同一个requests.session
,该变量可以在main函数最开始定义,如:session_requests = requests.session()
至此,我们拿到了ASP.NET_SessionId
,现在只需要先GET请求一次login_home.aspx
,然后将ASP.NET_SessionId
和其他信息提交到ValidateCode.aspx
就能将验证码保存下来,第一阶段就算完成了
第二部分:登录请求中__VIEWSTATE
、__VIEWSTATEGENERATOR
、__EVENTVALIDATION
的获取
先手动登录一次教务网,通过浏览器自带的抓包工具或者其他抓包软件,可以查看登陆中的所有请求。找到login_home.aspx
的请求,发现事情没我想象的简单:
首先header中有个名为ASP.NET_SessionId
的随机值,这个我们已经在第一步解决了
而提交的data中又有几个随机值:__VIEWSTATE
、__VIEWSTATEGENERATOR
、__EVENTVALIDATION
、dsdsdsdsdxcxdfgfg
、fgfggfdgtyuuyyuuckjg
,这下把我整蒙了,我们只输入了账号、密码和验证码,那这些值是哪来的呢?
通过分析、搜索,发现这三个值居然就藏在登录页面login_home.aspx
的源码中,所以我们只要请求一次这个网页,就能用正则表达式匹配到。而这个页面已经在获取验证码的时候请求过了,所以只需要把结果保存下来,直接获取就行了
VIEWSTATE = re.findall(r'''name="__VIEWSTATE" id="__VIEWSTATE" value="(.*?)"''', res)[0]
VIEWSTATEGENERATOR = re.findall(r'''name="__VIEWSTATEGENERATOR" id="__VIEWSTATEGENERATOR" value="(.*?)"''', res)[0]
EVENTVALIDATION = re.findall(r'''name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="(.*?)"''', res)[0]
第三部分:登录请求中dsdsdsdsdxcxdfgfg
、fgfggfdgtyuuyyuuckjg
的获取
通过反复查看网页代码,发现了这样两个函数:
function chkpwd(obj) {
if (obj.value != '') {
var s = md5(document.all.txt_asmcdefsddsd.value + md5(obj.value).substring(0, 30).toUpperCase() + '11342').substring(0, 30).toUpperCase();
document.all.dsdsdsdsdxcxdfgfg.value = s;
} else {
document.all.dsdsdsdsdxcxdfgfg.value = obj.value;
}
}
function chkyzm(obj) {
if (obj.value != '') {
var s = md5(md5(obj.value.toUpperCase()).substring(0, 30).toUpperCase() + '11342').substring(0, 30).toUpperCase();
document.all.fgfggfdgtyuuyyuuckjg.value = s;
} else {
document.all.fgfggfdgtyuuyyuuckjg.value = obj.value.toUpperCase();
}
}
然后通过断点单步调试,发现上述代码中chkpwd(obj)
函数中的obj.value
表示密码,通过审查元素发现,txt_asmcdefsddsd
为账号输入框的id。同理,chkyzm(obj)
函数中的obj.value
表示验证码
不难看出,dsdsdsdsdxcxdfgfg
的内容为:将密码用md5加密,取前30位转大写,然后与密码和学校代码(我们学校是11342,每个学校不一样)拼接,再进行md5加密取前30位转大写
fgfggfdgtyuuyyuuckjg
的内容为:将验证码转大写,用md5加密再取前30位转大写,然后与学校代码拼接,再进行md5加密取前30位转大写
def md5(str):
m = hashlib.md5()
m.update(str.encode("utf8"))
return m.hexdigest()
dsdsdsdsdxcxdfgfg = md5(userid + md5(pwd)[:30].upper() + "11342")[:30].upper() #userid为用户账号,即学号
fgfggfdgtyuuyyuuckjg = md5(md5(verty_text.upper())[:30].upper() + "11342")[:30].upper() #verty_text为验证码
至此,登录所需的全部参数都已解决!我们就可以进入教务网为所欲为了(滑稽)
后话
我是爱国守法好公民
我是爱国守法好公民
我是爱国守法好公民
富强 民主 文明 和谐
自由 平等 公正 法治
爱国 敬业 诚信 友善
原文地址: https://raichu.top/index.php/archives/19/