用Apache httpclient模擬登陸學生個人資訊系統
不同學校的教務系統設計應該會有不同,這裡就只針對我的學校。本文主要講作為純小白連返回碼302都還不懂的我是怎麼一步步整的。
我打算用的是java。
因為模擬登入這塊以前都沒做過,就簡單百度了下,找到了開發用的相應的包,比如httpclient,網上也有別人做好的程式碼上傳的,所以就先跑跑別人的程式碼試試唄,記住把需要的jar包先下好並匯入到工程,下面是別人的程式碼
package com.zb.util; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.AbstractHttpClient; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.apache.http.cookie.Cookie; public class postData { HttpResponse httpResponse; List<Cookie> cookies; String result = ""; String data = ""; public void getResult() { String url = "http://210.38.137.101:9080/xsxt/xsxt.jsp";// 海大 HttpClient httpclient = new DefaultHttpClient(); /* 建立HTTP Post連線 */ HttpPost httpPost = new HttpPost(url); List<NameValuePair> params = new ArrayList<NameValuePair>(); // 使用者名稱密碼 params.add(new BasicNameValuePair("userId", "xxxx")); params.add(new BasicNameValuePair("userPass", "xxx")); // 發出http request try { // 發出HTTP request /* 新增到httpPost提交的內容中 */ httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8")); // 執行 ,取得HTTPresponse httpResponse = httpclient.execute(httpPost); // 若狀態碼為200 ok if (httpResponse.getStatusLine().getStatusCode() == 200) { // 返回值正常 // 獲取返回的cookie cookies = ((AbstractHttpClient) httpclient).getCookieStore() .getCookies(); } /*String timestatus = "201011311229" + new SimpleDateFormat("MMddHHmmss").format(new Date());*/ // String kbURL = "http://210.38.137.101/pls/wwwbks/xk.CourseView"; // // 檢視HttpWatch裡相應的URL String cjURL = "http://210.38.137.101/pls/wwwbks/bkscjcx.yxkc"; /* 建立HttpGet聯機 */ HttpGet httpGet = new HttpGet(cjURL); httpGet.setHeader("Cookie", "JSESSIONID=" + cookies.get(0).getValue()); httpGet.setHeader("Referer", "http://210.38.137.101:9080/xsxt/left.jsp"); // httpResponse.setHeader("User-Agent", // "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"); HttpResponse response2 = new DefaultHttpClient().execute(httpGet); /* 若狀態碼為200 ok */ System.out.println("status=" + response2.getStatusLine().getStatusCode()); if (response2.getStatusLine().getStatusCode() == 200) { StringBuffer sb = new StringBuffer(); // 獲取響應實體 HttpEntity entity = response2.getEntity(); InputStream is = entity.getContent(); BufferedReader br = new BufferedReader(new InputStreamReader( is, "GB2312")); // 是讀取要改編碼的源,源的格式是GB2312的,安源格式讀進來,然後再對原始碼轉換成想要的編碼就行 while ((data = br.readLine()) != null) { sb.append(data); } result = sb.toString(); // 此時result中就是我們成績的HTML的原始碼了 } } catch (Exception e) { e.printStackTrace(); } // HttpClient httpclient2 = new DefaultHttpClient(); System.out.println(data); System.out.println(result); } public static void main(String[] args) { postData pd = new postData(); // pd.postData(); pd.getResult(); } }
畢竟目前小白,自然地,哪有那麼容易就成功的,於是乎就開始了漫長的找問題和解決問題的過程,中間還停了挺長一段時間,沒辦法課多別的事多,畢竟這個只是一個課餘的一個想法。我用的抓包工具是火狐下的httpfox,本想用httpwatch,可火狐上用不了,因為下的是basic版,ie竟然也用不了,老提示升級成profession版,暫時沒興趣,就湊活用先,個人覺得新手的關注點不是工具。
廢話說的有點多了。。。我就登資訊系統,就看post了什麼資料過去,沒錯,就是隻有stuid,pwd,
那不應該啊,看著別人的程式碼好像是對的樣子,不過有些地方還是有疑問的,比如這句:httpGet.setHeader("Cookie", "JSESSIONID="+ cookies.get(0).getValue());初次執行就是這報錯的,什麼空指標異常的,不懂乍回事唉。。。折騰了好久,抓的包一條條的看,看各個地址,並不斷在原有程式碼上各種調整,比如把上面這句刪掉了後,就跑起來了,但獲取的頁面文字是,請輸入賬號密碼之類就是根本就沒登入上的意思。仔細看程式碼可以知道是分成兩步的,前面是最開始的登入,後面跑去成績的頁面。既然登都沒登上,那就先主攻登入這塊,可是該post的都post啦,咋回事,當時也不懂cookies這東西,就在想是不是他的為題,經過各種百度,cookies是向服務端發出請求後服務端返回給客戶端也就是瀏覽器的一個標識,這樣你在登入後的操作就只需亮出你的cookies證明你已經登入過了,可以繼續逛。那麼就不該是cookies的問題了。剛剛突發奇想試了下post地址換成網頁登入頁面的,竟然失敗了,要知道中間停下來不做前好像一直用的是他啊,暈!所以提醒大家,抓包仔細看看post到哪個地址,並不是你在哪個頁面地址登入,就post到那,以我學校為例,抓包後明顯登入頁面是由幾個模組組合起來。。還是不行,那麼哪出事了,在百度過程我看到了重定向這個概念,也就是服務端返回了302,巧了,好像抓包時有,還有我發現在Post那條中的Query String裡有值
多次試驗是動態的,會不會和他們有關,在抓到的包中也發現了一個與此相關的js檔案,裡面是幾個函式,看起來就是和他的value值有關,還有抓包查看了post的地址,就是在原來的基礎上加上了jym2005=value,這時我還以為這就是重定向的地址.......如果搞到他再get就好了,理想總是豐滿,於是乎就開始研究怎麼獲取這個value,可弄了好久也沒結果,百度到的query String的東西都搞不懂是啥或者和這個有關係,我還百度怎麼直接獲取重定向後的地址,試了網上的各種方法,沒啥基礎,只能照著試唄,不能實現也不會改,但還是找到了一個可以用的httpResponse.getLastHeader("Location").getValue(); 我把它獲取的東西列印了出來,發現根本就不是什麼jym的,而是這個東西login2.loginmessage,天,這差的太遠了,然後就又一陣瞎搞,都無果而終,要是仔細點注意到上面右圖的第二條的地址就省很多時間了,login2.loginmessage不就是get的那個url,重定向本就是post後再get的,因為我之前試過直接用那第二條的url在瀏覽器開啟,結果是空白。。。沒錯繞了一圈用還是用httpResponse.getLastHeader("Location").getValue();完整的試了下,竟然可以登上了,現在弄出來後,發現jym啥的和得到的login2.loginmessage這兩者之間必定是存在某種聯絡的,後者不應該只是一個單純的字串,這可以後面研究研究,只要登入上了,那後面的查成績看課表就好弄了,就不多說了,另外我獲取cookies值得方式比較死板,若有好的方法感謝指教。
package test;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.AbstractHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.ExecutionContext;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.cookie.Cookie;
public class test {
HttpResponse httpResponse;
List<Cookie> cookies;
String result = "";
String cookie = "";
String data = "";
public void getResult() {
String url = "http://";// HIT
HttpClient httpclient = new DefaultHttpClient();
/* 建立HTTP Post連線 */
HttpPost httpPost = new HttpPost(url);
List<NameValuePair> params = new ArrayList<NameValuePair>();
// 使用者名稱密碼
params.add(new BasicNameValuePair("stuid", "xxxx"));
params.add(new BasicNameValuePair("pwd", "xxxx"));
// 發出http request
try {
// 發出HTTP request
/* 新增到httpPost提交的內容中 */
httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
// 執行 ,取得HTTPresponse
httpResponse = httpclient.execute(httpPost);
// 若狀態碼為302 重定向
if (httpResponse.getStatusLine().getStatusCode() == 302) {
// 獲取返回的cookie
cookies = ((AbstractHttpClient) httpclient).getCookieStore().getCookies();
Header[] headers = httpResponse.getAllHeaders();
cookie=headers[4].getValue();
cookie=cookie.substring(0,27);
//System.out.println(cookie);
String locationUrl=httpResponse.getLastHeader("Location").getValue();
/* 建立HttpGet聯機 */
HttpGet httpGet = new HttpGet("http://"+locationUrl);
httpGet.setHeader("Cookie", cookie);
HttpResponse response2 = new DefaultHttpClient().execute(httpGet);
/* 若狀態碼為200 ok */
if (response2.getStatusLine().getStatusCode() == 200) {
System.out.println("登入成功!");
HttpGet httpGet1 = new HttpGet("http://");
httpGet1.setHeader("Cookie", cookie);
HttpResponse response3 = new DefaultHttpClient().execute(httpGet1);
StringBuffer sb = new StringBuffer();
HttpEntity entity = response3.getEntity();
InputStream is = entity.getContent();
BufferedReader br = new BufferedReader(new InputStreamReader(is, "GB2312"));
while ((data = br.readLine()) != null) {sb.append(data);}
result = sb.toString(); // 此時result中就是我們成績的HTML的原始碼了
}else
System.out.println("重定向跳轉失敗,登入失敗!");
}else{
System.out.println("登陸失敗!");
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(data);
System.out.println(result);
}
public static void main(String[] args) {
test pd = new test();
pd.getResult();
}
}