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()方法我會稍後發出。



作者:薛勤,互聯網從業者,編程愛好者。

本文首發自公衆號:代碼藝術(ID:onblog)未經許可,不可轉載


本文分享自微信公衆號 - 代碼藝術(onblog)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章