引入:闲着没事想研究下学校查成绩的接口,然后自己写程序查。但是查成绩首先必须登录,所以必须先研究学校网站的登录接口,抓包后发现传到后台的学号密码是经过加密的,研究其加密方法成为必经之路
发现学校网站改造升级后并没有以前想的那么破烂了。登录的账号和密码都通过js进行了编码,所以想通过程序模拟登录,必须弄清楚进行编码操作的js代码,然后最重要的是还要把它翻译成java代码,但是由于js和java的语法还是有差别,有些函数也不是那么通用,再用java写一遍感觉有点麻烦。于是想到java能不能执接执行js代码,这样我只要传一个学号,密码给编码函数就可以获得编码后的结果,省事又快!!于是发现java在1.6版本就提供了支持,真实神通广大啊。
1.首先把js代码写在conwork.js文件里
var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
function encodeInp(input) {
var output = "";
var chr1, chr2, chr3 = "";
var enc1, enc2, enc3, enc4 = "";
var i = 0;
do {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64
} else if (isNaN(chr3)) {
enc4 = 64
}
output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + keyStr.charAt(enc3) + keyStr.charAt(enc4);
chr1 = chr2 = chr3 = "";
enc1 = enc2 = enc3 = enc4 = ""
} while (i < input.length);
return output
}
2.在java中定义一个接口,这个接口要有一个与要执行的javascript函数一样的方法签名。定义个Methods接口,内容如下:
package js;
/**
* 接口中的方法签名必须与要执行的JavaScript方法一致
*/
public interface Methods {
public String encodeInp(String input);
}
3.然后就开始跑咯!!
package js;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import java.io.FileReader;
public class ExecuteScript {
public static void main(String[] args) {
//创建一个脚本引擎管理器
ScriptEngineManager manager = new ScriptEngineManager();
//获取一个指定的名称的脚本引擎
ScriptEngine engine = manager.getEngineByName("js");
try {
//获取当前类的所在目录的路径
String path = ExecuteScript.class.getResource("").getPath();
// FileReader的参数为所要执行的js文件的路径
engine.eval(new FileReader(path + "conwork.js"));
if (engine instanceof Invocable) {
Invocable invocable = (Invocable) engine;
//从脚本引擎中返回一个给定接口的实现
Methods executeMethod = invocable.getInterface(Methods.class);
//执行指定的js方法
System.out.println(executeMethod.encodeInp("14142400755"));//
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
这是java运行上述js代码,学号编码后的结果图
问题又来了。通过上面代码,我们每需要执行一个新的js方法就重复写第三步的代码,存在重复操作,我们完全可以把它抽取成通用的方法,这样我们只要给定一个指定的方法接口,就可以获得一个方法的实例,操作起来简直不要太方便!
package js;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import java.io.FileReader;
public class ExecuteScript {
/**
* 从给定的js文件中获取指定接口中的方法的实例
* @param fileLoacation js文件路径
* @param clazz 接口的class
* @return 返回一个指定接口方法的实例
*/
public <T> T getMethod (String fileLoacation,Class<T> clazz) {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("js");
try {
String path = ExecuteScript.class.getResource("").getPath();
System.out.println(path);
// FileReader的参数为所要执行的js文件的路径
engine.eval(new FileReader(fileLoacation));
if (engine instanceof Invocable) {
Invocable invocable = (Invocable) engine;
T executeMethod = invocable.getInterface(clazz);
return executeMethod;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
测试用例:
package js;
/**
* Created by Administrator on 2017/7/2.
*/
public class Main {
public static void main(String args[]){
ExecuteScript executeScript = new ExecuteScript();
String path=Main.class.getResource("").getPath();
String fileLocation=path + "conwork.js";
//通过下面一行代码就可以获取指定接口中方法的实例
Methods method = executeScript.getMethod(fileLocation, Methods.class);
String result=method.encodeInp("14142400755");
System.out.println(result);
}
}
相关文章链接:
1.Java执行JavaScript代码http://www.jb51.net/article/81577.htm
2.JAVA执行javascript方法http://blog.csdn.net/jianggujin/article/details/51046122
3.如何在java中调用js方法http://www.cnblogs.com/langtianya/archive/2012/09/18/2690860.html