1. 程式人生 > >HttpWatch+HttpClient模擬登入學校教務系統

HttpWatch+HttpClient模擬登入學校教務系統

因為最近在做一個安卓專案,有查成績模組,而學校並不提供介面,也沒找到其他可用的API,無奈之下只能迴歸原始的模擬登入。

首先,我們得先弄明白我們校園網是怎麼工作的,這裡要用到HttpWatch,分析我們正常登入時的請求與響應資訊,當然你有chrome或fox之類的也行。我個人還是覺得HttpWatch看著要清晰些。

沒用過HttpWatch的自己下載研究琢磨下,這裡不作贅述。我這用的是HttpWatch Professional 7.0中文版。在登入頁面輸入你的使用者密碼,別急著確定,先點選HttpWatch左上角的紅色圓點,開始記錄,再點登入。


然後就會看見各種資訊嘩啦嘩啦湧過來了,無需跳轉的頁面完全載入好,你已經確定進來了就可以按停止了。



好,這時候我們的正常登陸就完成了,可以開始分析我們教務系統怎麼跳轉的了。

定位到第一條,我們可以知道,在我們點選了那個“登入”按鈕之後,首先執行了一條post方法,請求路徑為/portal/login.do,返回值為302,即重定向。究竟帶了什麼東西過去呢?我們點選下面的Post資料,可以看到這樣的:


顯然,帶了我們的使用者密碼過去了,並且沒有其他的多餘引數。這裡我們知道了一個重要資訊,使用者名稱和密碼的引數名分別為j_username,j_password。

我們都知道,HTTP是一個請求響應協議,既然發起了請求,那我們肯定得拿著響應裡的cookie資訊繼續訪問,哪些cookie是需要的呢?

定位第一條,點選頭資訊,如下


左邊是傳送過去的,右邊是傳送後返回接收的,可以看到,我們帶著使用者名稱密碼向login.do傳送請求後,返回了location(重定向的地址),Server(服務端資訊),以及5個Set-Cookie(服務端在客戶端再次發起請求前對客戶端Cookie的賦值)。這裡我們需要的是location和Set-Cookie。

定位到第二條,點頭資訊,可以看到,


經過與第一條返回的頭資訊對比,我們知道了,我們學校的教務平臺再次傳送請求攜帶的cookie裡有三個東西,分別第一條返回的Set-Cookie裡的第一項,第四項,第五項(據我所知有的學校返回的cookie裡只有一個鍵值對,因校而異)。

第二條的結果內容是這樣的


給了個路徑,所以有了第三條的get請求,而第三條返回內容類似,也是路徑



。。。。所以最終進去了的頁面和登入頁面是一個url


有點麻煩,這也是我不太喜歡用iframe來佈局的原因。好,現在我們知道整個流程了,開始碼農模式

首先寫個方法來處理我們的使用者名稱密碼,作為post攜帶的引數

<pre name="code" class="java">List<NameValuePair> parmasList = new ArrayList<NameValuePair>();
		HashMap<String, String> parmasMap = new HashMap<String, String>();
		parmasMap.put("j_username", userName);
		parmasMap.put("j_password", passWord);
		Set<String> keySet2 = parmasMap.keySet();
		for (String temp : keySet2) {
			parmasList.add(new BasicNameValuePair(temp, parmasMap.get(temp)));
		}


</pre><pre name="code" class="java">然後我們模擬向login.do執行Post,並取出返回的SetCookie,location等,處理並存放
<pre name="code" class="java">List<NameValuePair> parmasList = new ArrayList<NameValuePair>();
		parmasList = initLoginParmas("12209030071", "********");//密碼不給看
		HttpPost post = new HttpPost(LoginUrl);
		post.getParams().setParameter(ClientPNames.HANDLE_REDIRECTS, false);
		// 阻止自動重定向,目的是獲取第一個ResponseHeader的Cookie和Location
		post.setHeader("User-Agent",
				"Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko");
		post.setHeader("Content-Type",
				"application/x-www-form-urlencoded;charset=gbk");
		// 設定編碼為GBK
		post.setEntity(new UrlEncodedFormEntity(parmasList, "GBK"));
		HttpResponse response = new DefaultHttpClient().execute(post);
		Header[] headers = response.getHeaders("Set-Cookie");
		String JSESSIONID = headers[0].getValue().split(";")[0] + ";";
		String SECURITY_AUTHENTICATION_COOKIE = headers[3].getValue()
				.split(";")[0] + ";";
		String SECURE_AUTH_ROOT_COOKIE = headers[4].getValue().split(";")[0];
		cookie.append(JSESSIONID).append(SECURITY_AUTHENTICATION_COOKIE)
				.append(SECURE_AUTH_ROOT_COOKIE);
		// 取得cookie並儲存起來
		location = response.getFirstHeader("Location").getValue();
		// 重定向地址,目的是連線到主頁


</pre><pre name="code" class="java">-----------------------------------------------------------------------------------------------
我們已經完成最重要的第一步,拿到相關cookie了,接下來向上面的location執行get請求,並將我們已經拿到的cookie給它,再給它一些頭資訊以防萬一,模擬第二步。
<pre name="code" class="java">HttpGet get = new HttpGet(url);
		get.addHeader("Host", "Host");
		get.addHeader("Referer", Referer);
		get.addHeader("Connection", "Keep-Alive");
		get.addHeader("Cookie", cookie.toString());
		HttpResponse httpResponse = new DefaultHttpClient().execute(get);


</pre><pre name="code" class="java">在本例中,那個location其實沒什麼用,因為它的返回資訊就是一個js頁面跳轉,跳轉的頁面的原始檔又是一個js頁面跳轉。。。(分別指的是第二條第三條的返回內容)
經過觀察後中間的cookie沒有變化,所以掠過這些步驟,直接向最終的url發起該get請求,得到我們想要的頁面資訊。
<img src="https://img-blog.csdn.net/20160202221325562?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" width="1150" height="600" alt="" />
</pre><pre name="code" class="java">接下來,想要查成績,看課程表或檢視教務系統內其他一些個人資訊,如法炮製即可,最終顯示給使用者的資料可以再用正則表示式或一些爬蟲工具如jsoup等處理一下。