注意:本文以湖南工程学院教务网络管理系统(青果教务系统)为例,其他青果系统类似,本文只提供思路,不提供代码

  u1s1,这是我爬过最有趣的网站了,过程曲折而有意思


第一部分:验证码及ASP.NET_SessionId的获取

  这是学校教务网的首页,很明显,要登录的话至少需要账号密码验证码1.png

  很快就遇到了第一个难题——验证码的获取
  通过分析前端代码,不难发现整个登录页面是个单独的iframe2.png
  而且验证码也不是什么好招呼的主,本来想着用请求直接将验证码保存下来,结果发现这个请求的header中有个Cookie,里面有个ASP.NET_SessionId,并且是个随机值3.png
  通过查阅资料,发现这是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__EVENTVALIDATIONdsdsdsdsdxcxdfgfgfgfggfdgtyuuyyuuckjg,这下把我整蒙了,我们只输入了账号、密码和验证码,那这些值是哪来的呢?4.png
  通过分析、搜索,发现这三个值居然就藏在登录页面login_home.aspx的源码中,所以我们只要请求一次这个网页,就能用正则表达式匹配到。而这个页面已经在获取验证码的时候请求过了,所以只需要把结果保存下来,直接获取就行了5.png

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]



第三部分:登录请求中dsdsdsdsdxcxdfgfgfgfggfdgtyuuyyuuckjg的获取

  通过反复查看网页代码,发现了这样两个函数:

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表示验证码6.png
  不难看出,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为验证码

  至此,登录所需的全部参数都已解决!我们就可以进入教务网为所欲为了(滑稽)


最后修改:2020 年 11 月 17 日 01 : 52 PM
愿君多打钱,此物最相思