Android網絡開發實例(基于抓包實現的網絡模擬登錄,登出和強制登出)

yzming2012 7年前發布 | 8K 次閱讀 安卓開發 Android開發 移動開發

學習Android有幾個月了,最近喜歡上了網絡編程,于是想通過Android寫一些一個小程序用于連接外網.在這里非常感謝雪夜圣誕的支持,非常感謝,給我打開新的一扇門.

1.聲明,本程序只能用于西南大學連接外網登錄,其他網站需要自己進行抓包測試.

2.聲明,本文更多的是關注網絡抓包已經,本地構造,如果有什么錯誤,請盡情指教,非常感謝.

3.聲明,最后源代碼,以全部上傳github,需要的同志可以自行下載,文章結尾會附帶鏈接.

廢話不多說,正文開始:

學校官網

第一步,首先需要實現的是登錄操作:

當我們點擊登錄外網會出現以下頁面:

這個頁面時關鍵,我們就要在這個頁面進行抓包處理.我使用的是chorme瀏覽器,我打開chrome瀏覽器的開發者工具,從中選擇network進行信息監控以下界面:

這里需要關注的是,我們需要勾選上Preserve log,這樣頁面跳轉時,發送的信息就不會消失了.然后,我們點擊連接按鈕,我們我可以發現以下情況:

其實我們可以發現我們要實現登錄按鈕,我們需要使用的url就是第一個,我們點擊第一個url查看數據包詳情,這樣子我們就可以知道這個url需要哪些數據:

這里我們可以發現,其實瀏覽器是向這個url發送了一個post請求,在post中放置了如下數據(userId,password,service,queryString,operatroPwd,operatorUserId,validcode).

(弱弱的說一下,這里作者用自己的賬號做測試,希望技術大牛,不要來搞我.......),我們很容易就發現userId和passwordId(就是賬號和密碼),service經過我多次測試并不會改變,應該是固定值,除了queryString之外的屬性都是空的.難點就在這個queryString,我們點擊view source查看原來編碼(這里需要特別注意,瀏覽器會進行一次編碼顯示給我們,我們使用的應該是source原來的value值)

我們可以發現,其實兩者的內容都是一樣的,就是=編碼的格式不同而已,因此我們只要向http://222.198.127.170/發送一個get請求,然后把對應的內容截取出來就可以了.

因此登錄很簡單了,網址有了,填充的數據也知道了,我只要發送一個post請求就可以實現登錄功能了.這里貼一下登錄函數的代碼

    //進行登錄操作
    private boolean loginValidate(String username,String passwd) throws Exception
    {
        final String html = HttpUtil.sendGetRequest("http://222.198.127.170/", false, null, "gbk");
        //使用正則表達式獲取對應的填充數據
        String p = "jsp\\?(.+?)'</script>";
        Pattern reg = Pattern.compile(p);
        Matcher m= reg.matcher(html);
        String FillingStr = "";
        if(m.find())
        {
            FillingStr = m.group(1);
        }
        //這里需要注意,需要使用utf-8格式進行編碼
        FillingStr = URLEncoder.encode(FillingStr,"utf-8");
        final String url = "http://222.198.127.170/eportal/InterFace.do?method=login";
        final String data="userId="+username+"&password="+passwd+"&service=%25E9%25BB%2598%25E8%25AE%25A4&queryString="+FillingStr+"&operatorPwd=&operatorUserId=&validcode=";
        //發送登錄請求
        String html2=HttpUtil.sendPostRequest(url, data, false, null, "gbk");
        if(html2.contains("success"))
            return true;
        return false;
    }

HttpUtil是我自己寫的一個發送Http請求的工具類,我把工具類列出來,github中有源碼,需要的可以進行查閱.

package com.network.cjyong.networklogin.util;

/**
 * Created by cjyong on 2017/3/5.
 */

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

public class HttpUtil
{
    /**
     * 向對應的網址發送get請求,以String的形式返回服務器的相應
     *
     * @author cjyong at 2017/3/5
     * @param url 發送請求的網址
     * @param usecookie 是否使用cookie
     * @param cookie 需要攜帶的cookie
     * @param encoding 編碼格式
     * @return 以string的形式返回服務器的響應
     * @throws Exception
     */
    public static String sendGetRequest(final String url,final boolean usecookie,final String cookie,final String encoding) throws Exception
    {
        FutureTask<String> task = new FutureTask<String>(
                new Callable<String>()
                {
                    @Override
                    public String call() throws Exception
                    {
                        URL turl = new URL(url);
                        HttpURLConnection conn = (HttpURLConnection) turl.openConnection();
                        //設置時間限制,拋出異常
                        conn.setConnectTimeout(5000);
                        conn.setReadTimeout(5000);
                        conn.setRequestProperty("User-Agent", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)");
                        conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
                        if(usecookie)
                            conn.setRequestProperty("Cookie", cookie);
                        InputStream is = conn.getInputStream();
                        BufferedReader reader = new BufferedReader(new InputStreamReader(is,encoding));
                        StringBuilder sb = new StringBuilder();
                        String line = null;
                        while((line = reader.readLine())!= null)
                            sb.append(line+"\n");
                        return sb.toString();
                    }
                });
        //格外進行一個線程進行網絡操作,防止堵塞
        new Thread(task).start();
        return task.get();
    }

    /**
     * 向對應的網址發送post請求,以String的形式返回服務器的相應
     *
     * @author cjyong at 2017/3/5
     * @param url 發送請求的網址
     * @param data 發送post請求攜帶的數據
     * @param usecookie 是否使用cookie
     * @param cookie 需要攜帶的cookie
     * @param encoding 編碼格式
     * @return 以string的形式返回服務器的響應
     * @throws Exception
     */
    public static String sendPostRequest(final String url,final String data,final boolean usecookie,final String cookie,final String encoding) throws Exception
    {
        FutureTask<String> task = new FutureTask<String>(
                new Callable<String>()
                {
                    @Override
                    public String call() throws Exception
                    {
                        URL turl = new URL(url);
                        HttpURLConnection conn = (HttpURLConnection) turl.openConnection();
                        conn.setRequestMethod("POST");
                        conn.setDoOutput(true);
                        //設置時間限制,拋出異常
                        conn.setConnectTimeout(5000);
                        conn.setReadTimeout(5000);
                        conn.setRequestProperty("User-Agent", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)");
                        conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
                        if(usecookie)
                            conn.setRequestProperty("Cookie", cookie);
                        OutputStream outStream = conn.getOutputStream();
                        outStream.write(data.getBytes());
                        outStream.flush();
                        outStream.close();
                        InputStream is = conn.getInputStream();
                        BufferedReader reader = new BufferedReader(new InputStreamReader(is,encoding));
                        StringBuilder sb = new StringBuilder();
                        String line = null;
                        while((line = reader.readLine())!= null)
                            sb.append(line+"\n");
                        return sb.toString();
                    }
                });
        //格外進行一個線程進行網絡操作,防止堵塞
        new Thread(task).start();
        return task.get();
    }


    /**
     * 向對應的網址發送post請求,獲取對應的cookie,以備后用
     *
     * @author cjyong at 2017/3/5
     * @param url 發送請求的網址
     * @param data 發送post請求攜帶的數據
     * @return 以string的形式返回服務器的響應
     * @throws Exception
     */

    public static String getCookie(final String url,final String data)throws Exception
    {
        FutureTask<String> task = new FutureTask<String>(
                new Callable<String>()
                {

                    @Override
                    public String call() throws Exception
                    {
                        byte[] Data = data.getBytes();
                        URL turl=new URL(url);
                        HttpURLConnection conn = (HttpURLConnection)turl.openConnection();
                        conn.setRequestMethod("POST");
                        conn.setDoOutput(true);
                        //設置連接與讀取時間過期返回異常
                        conn.setConnectTimeout(5000);
                        conn.setReadTimeout(5000);
                        conn.setRequestProperty("User-Agent", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)");
                        conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
                        OutputStream outStream = conn.getOutputStream();
                        outStream.write(Data);
                        outStream.flush();
                        outStream.close();
                        String Cookie=conn.getHeaderField("Set-Cookie");
                        return Cookie;
                    }

                }
        );
        //格外進行一個線程進行網絡操作,防止堵塞
        new Thread(task).start();
        return task.get();
    }

}

登出功能類似,我這里就不在贅述了,貼一下登出函數的代碼:

    //進行登出操作
    private boolean logoutValidate() throws Exception
    {
        String html = HttpUtil.sendGetRequest("http://222.198.127.170/eportal/InterFace.do?method=logout",false,null,"utf-8");
        if(html.contains("success"))
            return true;
        return false;
    }

最后來講一下,強制下線功能的實現(這個需要用到cookie進行信息的交流,比較有代表性)

在學校網絡管理中心,有校園網推出選項,當我們點擊時,會出現如下情況:

這說明,強制下線并不是單純向一個url發送一個鏈接就可以完成的,在這里我們就需要進行抓包處理:

這里我們可以發現,這里發送的請求也很簡單,就是向login_judge.jsf發送一個post請求,post中數據也很簡單,就兩個內容(name,password)

然后我們點擊我的設備,就可以進行退出網絡操作了,我們截取一下包:

我們可以發現,這里需要向userself_ajax.jsf?methodName=xxxxx,發送一個post請求,其中數據特別簡單一個key和一串數字,并沒有用戶名和密碼,而Cookie中出現了,很明顯2個頁面之間的交流是通過cookie來是實現的,所以我們需要在登錄的頁面獲取對應的cookie進行編輯,向這個url發送post請求.難點在于,封裝的第二個數據是什么?這里就要進行苦逼的網頁代碼查詢了,我們點開onlinedevice_list.jsf進行代碼查詢: (由于網頁代碼太長了,我截取一部分有用的進行分享)

我們可以發現的第二個數據,其實就是我們不同設備的局域網ip地址,這樣子,數據也獲取到了,cookie也得到了,我們只要向指定url發送post請求就可以了.

這里貼一下強制下線函數的代碼:

 //進行強制下線操作
    private boolean forceLogoutValidate(String username,String passwd) throws Exception
    {
        //構造填充參數
        String data ="name="+username+"&password="+passwd;
        String url= "http://service2.swu.edu.cn/selfservice/module/scgroup/web/login_judge.jsf";
        //構造cookie
        String Cookie=HttpUtil.getCookie(url,data);
        Cookie=String.format(Cookie+" rmbUser=true; userName=%s; passWord=%s; oldpassWord=%s;", username,passwd,passwd);
        String listurl= "http://service2.swu.edu.cn/selfservice/module/webcontent/web/onlinedevice_list.jsf";
        String html= HttpUtil.sendGetRequest(listurl, true, Cookie, "gbk");
        //賬號密碼錯誤
        if(html.contains("您還未登錄或會話過期"))
            return false;
        //獲取設備的IP地址構造填充數據
        String p = "<span id=\"a1\">IP : (.+?)</span >";
        Pattern reg = Pattern.compile(p);
        Matcher m=reg.matcher(html);
        //將所有的設備進行下線
        while(m.find())
        {
            //執行下線操作
            String myurl = "http://service2.swu.edu.cn/selfservice/module/userself/web/userself_ajax.jsf?methodName=indexBean.kickUserBySelfForAjax";
            String mydata = "key= "+username+":" +m.group(1);
            HttpUtil.sendPostRequest(myurl, mydata, true, Cookie, "utf-8");
        }
        return true;
    }

到這里,所有的重要的函數和抓包方法都已經講解完畢,最后貼一下手機APP的截圖:

貼一下github地址(歡迎補充):

https://github.com/cai123nb/NetworkLogin/tree/master/main

講點廢話,其實我們可以看出,編碼并不困難,困難的使我們怎么抓取準確的網址和數據包,怎么填充正確的數據包.

只要我們這一點學習的好的話,,我們可以拓展開來,抓手機號碼的歸屬地,郵件/快遞的送達地址等,都是可以的.

第二,其實我的HttpUtil有點過時了,現在大多數的高手都是使用HttpClient,因為HttpClient支持https,我用老版的用順手,也就沒有換了,如果

有人有不同的思路歡迎補充.在這里,拋磚引玉了,你我共勉.

 

 

來自:http://www.cnblogs.com/cjyong/p/6506087.html

 

 本文由用戶 yzming2012 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!