【Java】模拟登录教务网并获取数据
本文章仅做技术交流演示学习,请勿用于违法操作!
前期准备
首先我们需要到要模拟登录的网页,进行抓包操作。
使用Chrome浏览器打开系统的登录页面,按F12打开开发者工具
切换到Network选项卡

然后正常进行登录操作。
登录成功后,可以在右面看到加载出很多的数据,我们需要逐一查看Headers找到对应的登录接口
如图所示,大部分都是login相关的页面名称。

很显然,这个接口URL即我们想要的请求登录接口。
RequestURL:http://打码/jsxsd/xk/LoginToXk

根据登录界面和FormData 我们知道,登录提供的是账户和密码,但是浏览器在请求的时候是三个参数,分别为:userAccount,userPassword,encoded
显然userAccount即我们提供的账号,userPassword是密码但为空,encoded是一堆看不懂的密文
初步推测是encoded应该是加密过后的密码
那么加密过程一定是在前端完成的,我们根据经验加密函数应该也是使用js写的。
回到登录界面,开启开发者模式,刷新一下,果然在列表中有一个名为conwork.js的文件

该文件就是用来对密码进行加密的文件,我们将其保存下来。
eval(function(p, a, c, k, e, d) {
e = function(c) {
return (c < a ? "" : e(parseInt(c / a))) + ((c = c % a) > 35 ? String.fromCharCode(c + 29) : c.toString(36))
}
;
if (!''.replace(/^/, String)) {
while (c--)
d[e(c)] = k[c] || e(c);
k = [function(e) {
return d[e]
}
];
e = function() {
return '\\w+'
}
;
c = 1;
}
;while (c--)
if (k[c])
p = p.replace(new RegExp('\\b' + e(c) + '\\b','g'), k[c]);
return p;
}('b 9="o+/=";p q(a){b e="";b 8,5,7="";b f,g,c,1="";b i=0;m{8=a.h(i++);5=a.h(i++);7=a.h(i++);f=8>>2;g=((8&3)<<4)|(5>>4);c=((5&s)<<2)|(7>>6);1=7&t;k(j(5)){c=1=l}v k(j(7)){1=l}e=e+9.d(f)+9.d(g)+9.d(c)+9.d(1);8=5=7="";f=g=c=1=""}u(i<a.n);r e}', 32, 32, '|enc4||||chr2||chr3|chr1|keyStr|input|var|enc3|charAt|output|enc1|enc2|charCodeAt||isNaN|if|64|do|length|ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789|function|encodeInp|return|15|63|while|else'.split('|'), 0, {}))
到此,前期准备就完成了。
模拟登录
本文使用Java来进行编写,其他语言原理类似。
Java运行JS代码
首先要解决的就是,如何能在java代码中运行这个使用js编写的加密函数。
当然,如果有能力看懂的话,你也可以重写一遍这个方法,可以跳过本段内容。
我们使用的是Java自带的解决方案:ScriptEngineManager
首先编写一个通用方法:
/**
* 从给定的js文件中获取指定接口中的方法的实例
* @param js js字符串
* @param clazz 接口的class
* @return 返回一个指定接口方法的实例
*/
public <T> T getMethod (Class<T> clazz,String js) {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("js");
try {
//1.可以直接读取指定目录下的文件
//String path = ExecuteScript.class.getResource("").getPath();
//System.out.println(path);
// FileReader的参数为所要执行的js文件的路径
//engine.eval(new FileReader(fileLoacation));
//2.直接加载字符串
engine.eval(js);
if (engine instanceof Invocable) {
Invocable invocable = (Invocable) engine;
T executeMethod = invocable.getInterface(clazz);
return executeMethod;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
然后根据Js的方法创建一个接口,接口中的方法名称要和js中的方法名称对应。
public interface JSMethods {
public String encodeInp(String input);
}
使用方法:
/**
* 加密
* @param onecard 学号
* @param password 密码
* @return 加密的学号+%%%+加密的密码
* */
private String getEncodeString(String onecard,String password){
ExecuteScript executeScript = new ExecuteScript();
//String fileLocation="src/main/resources/templates/conwork.js";
//通过下面一行代码就可以获取指定接口中方法的实例
JSMethods method = executeScript.getMethod(JSMethods.class,JscriptMethod.data);
String result=method.encodeInp(onecard);
String pass=method.encodeInp(password);
return result+"%%%"+pass;
}
这里的result是根据实际encoded结果分析出来的。
使用Okhttp进行模拟Post请求
首先创建请求体:requestbody
RequestBody requestBody=new FormBody.Builder()
.add("userAccount",account)
.add("userPassword","")
.add("encoded",getEncodeString(account,password))
.build();
必须与我们前面分析出来的请求参数一一对应。
接着我们创建一个request请求:
Request request=new Request.Builder()
.url(REQUEST_JW_URL)
.header("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")
.header("User-Agent","Mozilla")
.post(requestBody)
.build();
这里的请求头,可以参考浏览器获取的结果

然后使用okhttpclient发起post请求即可,根据response判断是否登录成功
/**
* 模拟登陆
* @param account 学号
* @param password 密码
* */
private String login(String account,String password){
String result="";
RequestBody requestBody=new FormBody.Builder()
.add("userAccount",account)
.add("userPassword","")
.add("encoded",getEncodeString(account,password))
.build();
Request request=new Request.Builder()
.url(REQUEST_JW_URL)
.header("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")
.header("User-Agent","Mozilla")
.post(requestBody)
.build();
try {
Response response=client.newCall(request).execute();
result=response.body().string();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
如果需要登录后进行访问其他页面获取数据,这里只需要配置一下okhttp的cookies管理工具:
public OkHttpClient client = new OkHttpClient.Builder()//这个cookies就不存在本地了,因为不需要验证码直接登录,每次刷新就好
.cookieJar(new CookieJar() {
@Override
public void saveFromResponse(HttpUrl httpUrl, List<Cookie> list) {
cookieStore.put(httpUrl.host(), list);
} @Override
public List<Cookie> loadForRequest(HttpUrl httpUrl) {
List<Cookie> cookies = cookieStore.get(httpUrl.host());
return cookies != null ? cookies : new ArrayList<Cookie>();
}
})
.build();
全局都使用该client进行请求即可,注意无论是同步还是异步操作都要保证login成功
【Java】模拟登录教务网并获取数据的更多相关文章
- Java模拟登录系统抓取内容【转载】
没有看考勤的习惯,导致我的一天班白上了,都是钱啊,系统也不发个邮件通知下.... 为了避免以后还有类似状况特别写了个java模拟登录抓取考勤内容的方法(部分代码来自网络),希望有人修改后也可以 ...
- Python爬虫实战五之模拟登录淘宝并获取所有订单
经过多次尝试,模拟登录淘宝终于成功了,实在是不容易,淘宝的登录加密和验证太复杂了,煞费苦心,在此写出来和大家一起分享,希望大家支持. 温馨提示 更新时间,2016-02-01,现在淘宝换成了滑块验证了 ...
- Python 爬虫实战5 模拟登录淘宝并获取所有订单
经过多次尝试,模拟登录淘宝终于成功了,实在是不容易,淘宝的登录加密和验证太复杂了,煞费苦心,在此写出来和大家一起分享,希望大家支持. 本篇内容 python模拟登录淘宝网页 获取登录用户的所有订单详情 ...
- 使用进程池模拟多进程爬取url获取数据,使用进程绑定的回调函数去处理数据
1 # 使用requests请求网页,爬取网页的内容 2 3 # 模拟使用进程池模拟多进程爬取网页获取数据,使用进程绑定的回调函数去处理数据 4 5 import requests 6 from mu ...
- Java模拟登录带验证码的教务系统(原理详解)
一:原理 客户端访问服务器,服务器通过Session对象记录会话,服务器可以指定一个唯一的session ID作为cookie来代表每个客户端,用来识别这个客户端接下来的请求. 我们通过Chrome浏 ...
- JAVA模拟登录实例
近期在做公司一个web项目.要求在我们的系统上,可以显示其它站点上的数据. 刚開始接到这个任务时,还在想.简单的非常.直接用UrlConection直接进入该网页,然后获取该网页的html,取到想要的 ...
- 模拟登录,发送amf类型数据
参考 http://blog.csdn.net/amandag/article/details/5666219 以及 稍微修改了一下AMFPost的类 一.登录 登录过程中主要用到标红的3个请 ...
- urllib库利用cookie实现模拟登录慕课网
思路 1.首先在网页中使用账户和密码名登录慕课网 2.其次再分析请求头,如下图所示,获取到请求URL,并提取出cookie信息,保存到本地 3.最后在代码中构造请求头,使用urllib.request ...
- Scrapy模拟登录赶集网
1.打开赶集网登录界面,先模拟登录并抓包,获得post请求的request参数 2. 我们只需构造出上面的参数传入formdata即可 参数分析: setcookie:为自动登录所传的值,不勾选时默认 ...
随机推荐
- openjudge 拯救公主
点击打开题目 看到这道题,第一感觉是我有一句m2p不知当讲不当讲 传送门就算了,你提莫还来宝石,还不给我每种最多有几个~~ 在一般的迷宫问题里,无论已经走了多少步,只要到达同一个点,状态便是等价的,但 ...
- Easy C 编程 in Linux
入坑Ubuntu有4,5天了,当时各种不习惯,但现在渐渐喜欢上了这种简单大方的显示界面和快速高效的命令行模式,各种没有的功能也都有网页版,非常不错呢. 现在最让我感到神奇之处,便是Linux的C编程是 ...
- Java的String类常用方法
一.构造函数 String(byte[ ] bytes):通过byte数组构造字符串对象. String(char[ ] value):通过char数组构造字符串对象. String(Sting or ...
- Java多线程:实现API接口创建线程方式详解
先看例子: /**实现Runnable接口创建线程步骤: * 1.创建一个实现Runnable接口的类 * 2.重写Runnable类中抽象的run()方法 * 3.创建实现类的对象 * 4.声明Th ...
- composer intall 报错
报错 [Composer\Exception\NoSslException] The openssl extension is required for SSL/TLS protection but ...
- http--->http缓存机制系统梳理
http缓存 HTTP请求的过程 从在浏览器地址栏敲入域名-DNS解析-实际IP-(中间可能多个代理服务器分发)- 源服务器,请求抵达源服务器后,在服务器上找到请求的资源,再通过代理服务器一层层的返回 ...
- delphiXE开发蓝牙BLE4.0程序时遇到的notification问题
IDE环境delphiXE8 蓝牙硬件ST17H26 service:0xfee7 chareter:0xfec9 const u16 my_OEMServiceUUID=0xfee7;const u ...
- Jquery 替换全部字符
item.replace('P','') 只会替换第一个'P'字符 item.replace(/P/gm,'') 替换全部'P'字符
- ROS中的3D建模机器人(三)
一.利用xacro理解机器人建模 当我们创建复杂的机器人模型时,URDF的灵活性将会降低,URDF缺少的主要特性是简单的.可重用性,模块化和可编程性. URDF是一个单独的文件我们不能在它里面包含其他 ...
- ros之发布者和订阅者协同工作
前面的例子显示了单个发布者/单个订阅者的情况,但是一个节点也可以同时是一个发布者和订阅者,或者拥有多个订阅和发布. 实际上,ROS节点最常做的事情是传递消息,并在消息上进行运算. 例doubler.p ...