Java模拟登录带验证码的教务系统(原理详解)
一:原理
- 客户端访问服务器,服务器通过Session对象记录会话,服务器可以指定一个唯一的session ID作为cookie来代表每个客户端,用来识别这个客户端接下来的请求。
- 我们通过Chrome浏览器进行网页访问时,服务器会在我们第一次请求时就建立会话生成Session对象,然后给我们的浏览器返回该Session ID,并把Session的ID保存在客户机的Cookie中,如图:
- 我们的每次请求都带上我们的Cookie,就可以实现会话状态的保持。
二:代码
- Jsoup应该是Java最简单的网页解析框架
- 下载地址:https://jsoup.org/download
- 该实例以强智教务系统为例:http://jwxt.qlu.edu.cn
package cn.zyzpp.eduCookie;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import org.jsoup.Connection;
import org.jsoup.Connection.Method;
import org.jsoup.Connection.Response;
import org.jsoup.Jsoup;
import org.junit.Before;
import org.junit.Test;
import cn.zyzpp.eduCookie2.S;
/**
* 模拟登录带验证码的教务系统
*
* 2018-2-9
*/
public class JsoupSafeCode {
private String url_safecode = "http://jwxt.qlu.edu.cn/verifycode.servlet?t=0.020974584"; // 验证码
private String url_encode = "http://jwxt.qlu.edu.cn/Logon.do?method=logon&flag=sess"; // 加密字符串
private String url_Login = "http://jwxt.qlu.edu.cn/Logon.do?method=logon"; // 登录
private String username = "";
private String password = "";
private String path = JsoupSafeCode.class.getResource("/").getPath().replaceAll("%20", " ") + "safecode.png";
private Map<String, String> cookie;
/**
* 下载验证码
* 保存Cookie
* @throws IOException
*/
public void getSafeCode() throws IOException {
Response response = Jsoup.connect(url_safecode).ignoreContentType(true) // 获取图片需设置忽略内容类型
.userAgent("Mozilla").method(Method.GET).timeout(3000).execute();
cookie = response.cookies();
byte[] bytes = response.bodyAsBytes();
Util.saveFile(path, bytes);
System.out.println("保存验证码到:" + path);
}
/**
* 登录教务系统
*/
public void initLogin() throws IOException {
S.print("输入验证码:");
Scanner scan = new Scanner(System.in);
String code = scan.next();
try {
Map<String, String> data = new HashMap<String, String>();
data.put("view", "1");
data.put("encoded", getEncoded());
data.put("RANDOMCODE", code);
Connection connect = Jsoup.connect(url_Login)
.header("Accept",
"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8")
.userAgent("Mozilla").method(Method.POST).data(data).timeout(3000);
for (Map.Entry<String, String> entry : cookie.entrySet()) {
connect.cookie(entry.getKey(), entry.getValue());
}
Response response = connect.execute();
S.println(response.parse().text().toString());
} catch (IOException e) {
}
}
/**
* 加密参数(依具体环境而定,加密算法一般在JS中获得)
*/
public String getEncoded() {
try {
Connection connect = Jsoup.connect(url_encode)
.header("Accept",
"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8")
.userAgent("Mozilla").method(Method.POST).timeout(3000);
for (Map.Entry<String, String> entry : cookie.entrySet()) {
connect.cookie(entry.getKey(), entry.getValue());
}
Response response = connect.execute();
String dataStr = response.parse().text();
// 把JS中的加密算法用Java写一遍:
String scode = dataStr.split("#")[0];
String sxh = dataStr.split("#")[1];
String code = username + "%%%" + password;
String encoded = "";
for (int i = 0; i < code.length(); i++) {
if (i < 20) {
encoded = encoded + code.substring(i, i + 1)
+ scode.substring(0, Integer.parseInt(sxh.substring(i, i + 1)));
scode = scode.substring(Integer.parseInt(sxh.substring(i, i + 1)), scode.length());
} else {
encoded = encoded + code.substring(i, code.length());
i = code.length();
}
}
return encoded;
} catch (IOException e) {
}
return null;
}
}
package cn.zyzpp.eduCookie;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class Util {
/**
* 将字节流转换成文件
*
* @param filename
* @param data
* @throws Exception
*/
public static void saveFile(String filename, byte[] data) {
if (data != null) {
String filepath = filename;
File file = new File(filepath);
if (file.exists()) {
file.delete();
}
try {
FileOutputStream fos = new FileOutputStream(file);
fos.write(data, 0, data.length);
fos.flush();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
后记
在模拟登陆该教务系统时,笔者观察到该教务系统还有一个不需要验证码即可登陆的网址:http://jwxt.qlu.edu.cn/jsxsd/xsxk/xklc_list,不过这个需要把用户名和密码通过JS算法进行前端加密合成为encoded字符串,如下
String encoded = playJs(username) + "%%%" + playJs(password);
然后直接带参POST即可。
具体的playJs()方法参考我的另一篇博客:Java执行JavaScript脚本破解encodeInp()加密
Java模拟登录带验证码的教务系统(原理详解)的更多相关文章
- php使用curl模拟登录带验证码的网站[开发篇]
需求是这样的,需要登录带验证码的网站,获取数据,但是不可能人为一直去记录数据,想通过自动采集的方式进行,如下是试验出来的结果代码!有需要的可以参考下! <?php namespace Home\ ...
- php使用curl模拟登录带验证码的网站
需求是这样的,需要登录带验证码的网站,获取数据,但是不可能人为一直去记录数据,想通过自动采集的方式进行,如下是试验出来的结果代码!有需要的可以参考下! <?php namespace Home\ ...
- 在Android上模拟登录广工正方教务系统查询成绩
这是在博客园里开博以来写的第一篇博客. 因为之前看过很多人都有发过关于模拟登录正方软件获取数据的文章,自己觉得挺好玩的便也去动手一做,开始还以为挺难的,但实际做起来还蛮简单的,当然其中还有些小插曲. ...
- Python爬虫模拟登录带验证码网站
问题分析: 1.爬取网站时经常会遇到需要登录的问题,这是就需要用到模拟登录的相关方法.python提供了强大的url库,想做到这个并不难.这里以登录学校教务系统为例,做一个简单的例子. 2.首先得明白 ...
- HttpURLConnection模拟登录学校的正方教务系统
教务系统登录界面 如图1-1 1-1 F12-->network查看登录教务系统需要参数: __VIEWSTAT txtUserName TextBox2 txtSecretCode Radio ...
- Java面试必问通信框架NIO,原理详解
NIO 流与块 通道与缓冲区 缓冲区状态变量 文件 NIO 实例 选择器 套接字 NIO 实例 内存映射文件 NIO与IO对比 Path Files NIO 新的输入/输出 (NIO) 库是在 JDK ...
- 【Java】【JVM】Sychronized底层加锁原理详解
我们首先先看看JMM模型,话不多说,上图: JMM对应的8大原子操作: read(读取):从主内存读取数据 load(载入):将主内存读取到的数据写入工作内存 use(使用):从工作内存读取数据来计算 ...
- Java模拟登录系统抓取内容【转载】
没有看考勤的习惯,导致我的一天班白上了,都是钱啊,系统也不发个邮件通知下.... 为了避免以后还有类似状况特别写了个java模拟登录抓取考勤内容的方法(部分代码来自网络),希望有人修改后也可以 ...
- [PHP自动化-进阶]002.CURL模拟登录带有验证码的网站
引言:继前文<模拟登录并采集数据>,大家似乎看不过瘾,这会再出一发,模拟实现带验证码网站的登录. 这篇文章主要介绍了PHP使用CURL实现对带有验证码的网站进行模拟登录的方法,可以帮助读者 ...
随机推荐
- jQuery如何判断input元素是否获得焦点(点击编辑时)
问题提出 如果你要判断input元素是否获得焦点,或者是否处在活动编辑状态,使用jQuery的 hasFocus() 方法或 is(':focus') 方法貌似都无效!搜索网上给出的办法,几乎净是采用 ...
- 关于正餐智能POS6.0.1.1改版后,点击反结账进入点菜界面后无法进行加菜的FAQ
适用版本:智能POS正餐V6.0.1.1+适用情况:点击反结账进入点菜界面后无法进行加菜.原因:为让报表统计的数据更准确解决方案:1.点击反结账,输入用户密码,进入点菜界面. 2.点击结算,进入收银台 ...
- 智能POS删除文件和数据库操作步骤
1. 2. 3. 4.winbox:日志:winboxcash:数据库:winboxcyb:其他文件: 5.删除以上三个文件夹
- asp.net Web项目中使用Log4Net进行错误日志记录
使用log4net可以很方便地为应用添加日志功能.应用Log4net,开发者可以很精确地控制日志信息的输出,减少了多余信息,提高了日志记录性能.同时,通过外部配置文件,用户可以不用重新编译程序就能 ...
- SQL Prompt 快捷键
推荐一个小插件,SQL Prompt,配合Microsoft SQL Server Management Studio,使用起来非常方便,同时再加上以下几个快捷键: (1)ctrl+5或F5,运行代码 ...
- c/c++ 标准库 set 自定义关键字类型与比较函数
标准库 set 自定义关键字类型与比较函数 问题:哪些类型可以作为标准库set的关键字类型呢??? 答案: 1,任意类型,但是需要额外提供能够比较这种类型的比较函数. 2,这种类型实现了 < 操 ...
- NPOI 笔记
前言 文档:http://npoi.codeplex.com/documentation 示例:https://npoi.svn.codeplex.com/svn/ 下载:https://www.nu ...
- 【Ubuntu16.04.4】常用配置
1.为root用户设置密码 sudo passwd root 2.设置用户登陆界面 sudo gedit /usr/share/lightdm/lightdm.conf.d/50-unity-gre ...
- [Hive_add_11] Hive 使用 UDTF 实现日志降维
0. 说明 对日志进行降维处理,将日志分为几个小表 通过编写 UDTF ,对日志降维,将日志聚合体相关字段抽取出来,形成新表. 1. 操作流程 1.0 日志部分内容 ##{\"appChan ...
- java求解第N个素数(质数)
面试中,遇到一个题目:求解第N个素数. import java.util.Scanner; public class GetPrimeNumber { public static int NthPri ...