抓取2020年最新版正方教务系统——在Android执行JS脚本实现AES加密

在之前的文章从零开始开发一个自动抓取教务系统课表等信息并动态显示的安卓课程表APP,原理分析及功能实现完美教程中,详细介绍了使用HttpClient抓取教务系统的方法,但是本次正方教务系统又㕛叒叕升级了,改用了AES加密,那本次就来分析并解决这个问题。

一、问题复现

在今天改进WTUCloud项目时,偶然发现一直无法登录教务系统,并提示200错误,尝试无数次后,依然没有办法,最终去官网查看,发现首页都变了——又更新了,使用Firefox抓包
抓取2020年最新版正方教务系统——在Android执行JS脚本实现AES加密_第1张图片
可以看到密码变成了一串108字符的乱码RiB7brPAbkG********************NECmOaPHFUlXwpJbVi5Eh1gr15pw9wwo/1a3Xs=
果断翻看登陆界面源代码,发现多了如下内容:
一段id为pwdDefaultEncryptSalt的字符串
在这里插入图片描述
多了一个名为_etd2的函数
抓取2020年最新版正方教务系统——在Android执行JS脚本实现AES加密_第2张图片
以及一个名为encrypt的脚本文件
抓取2020年最新版正方教务系统——在Android执行JS脚本实现AES加密_第3张图片
整理阅读代码后,在其中发现了如下函数:

function encryptAES(data, _p1) {
	if (!_p1) {
		return data;
	}
	var encrypted = _gas(_rds(64) + data, _p1, _rds(16));
	return encrypted;
}

根据这一个函数就可以得出如下结论:

  • 刚刚的108位乱码是密码解析AES-CBC加密后的结果
  • 在AES加密同时使用了Base64和Base16编码
  • pwdDefaultEncryptSalt为加密公钥

有了如上结论,就可以手动模拟进行AES加密了

二、实现AES加密

为了防止教务系统的加密方式改动,这里使用教务系统云端的加密函数,不在本地存储,同之前模拟登录一样,使用GET方法抓取加密JS脚本

 RequestConfig config = RequestConfig.custom().setRedirectsEnabled(false).build();//不允许重定向
        CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(config).build();//配置浏览器
        String url="https://auth.wtu.edu.cn/authserver/custom/js/encrypt.js";
        HttpGet httpGet=new HttpGet(url);
        CloseableHttpResponse response=httpClient.execute(httpGet);
        HttpEntity httpEntity=response.getEntity();
        //获取js
        String js= EntityUtils.toString(httpEntity,"UTF-8");

抓取到JS脚本后,使用ScriptEngineManager创建一个JS脚本运行器来执行

 ScriptEngine engine = new ScriptEngineManager().getEngineByName("javascript");
        //写入函数
        engine.eval(js);
        //实例化引用
        Invocable invoke = (Invocable) engine;

最后返回所需要的结果

String ans= (String) invoke.invokeFunction("encryptAES",password,pwdkey);

注意!password是用户密码,需要手动输入,pwdkey是加密公钥,可以直接从登录页面抓取,方法同之前抓取lt一样

//得到公钥
        pwdkey=body.select("[id=pwdDefaultEncryptSalt]").attr("value");
        System.out.println("pwdkey: " +pwdkey);

三、在安卓上如何使用JS

刚刚方法测试环境为IDEA,可以完美通过,但是SDK中没有ScriptEngineManager的API接口,这时候只需要在gradle.app中加入如下依赖即可启用:

implementation 'io.apisense:rhino-android:1.0'


最后将加密后的ans替换passwrod即可,其他流程同之前一样,就不在赘述,具体请参考上一篇文章,更新后的源码以及同步上传到Github,有需要的可以自取

Githu地址:Android-JAVA-ZFeducation-system

记录不易,查阅了很多资料,写笔记的初心是希望大家日后遇到同样问题,可以少走弯路,我为人人,人人为我,有用的话,记得点个赞哦~

你可能感兴趣的:(抓取2020年最新版正方教务系统——在Android执行JS脚本实现AES加密)