使用OkHttp進(jìn)行重定向攔截處理

網(wǎng)上有很多的OkHttp的教程物延,但是并沒有一個(gè)是關(guān)于如何OkHttp處理重定向的。這里的處理重定向的意思是:把重定向請(qǐng)求攔截下來瘩将,然后我們自己去請(qǐng)求重定向后的網(wǎng)頁锐涯,然后通過Jsoup解析自己需要的網(wǎng)頁數(shù)據(jù)。比如說我們模擬用戶登錄嗦篱,然后自己去請(qǐng)求解析登陸后跳轉(zhuǎn)的網(wǎng)頁的內(nèi)容冰单。為什么要做這樣的一個(gè)東西呢?比如說課程表的查成績(jī)功能灸促,就可以使用這種方法來獲取成績(jī)诫欠。

大概的原理是怎樣的呢?
我們先來說一下瀏覽器是怎么樣做用戶登錄的:瀏覽器會(huì)將你輸入的帳號(hào)和密碼通過POST請(qǐng)求攜帶過去浴栽,當(dāng)然可能還會(huì)有其它字段荒叼,因?yàn)檫@個(gè)POST請(qǐng)求是我們網(wǎng)頁和服務(wù)器規(guī)定好的;登錄成功后典鸡,服務(wù)器會(huì)返回一個(gè)Set-Cookie請(qǐng)求頭字段被廓,有了Cookie瀏覽器就可以通過GET請(qǐng)求訪問登錄后的網(wǎng)頁,注意沒有這個(gè)Cookie是無法請(qǐng)求登陸后的網(wǎng)頁的椿每,GET請(qǐng)求必須設(shè)置Cookie請(qǐng)求頭字段伊者,將服務(wù)器返回的Cookie攜帶過去。

明白了瀏覽器的行為之后间护,我們知道需要做的步驟就是4步:

  1. 自己做POST請(qǐng)求,并且不讓它自動(dòng)重定向
  1. 我們拿到POST請(qǐng)求返回來的響應(yīng)挖诸,獲取對(duì)應(yīng)的Set-Cookie字段的內(nèi)容
  2. 將該對(duì)應(yīng)的內(nèi)容添加到GET請(qǐng)求的Cookie請(qǐng)求頭字段中汁尺,然后做GET請(qǐng)求
  3. 獲取到的GET請(qǐng)求的響應(yīng)體就是我們登陸后的網(wǎng)頁內(nèi)容了,如果是靜態(tài)網(wǎng)頁可以通過Jsoup解析自己想要的信息了

我們需要通過抓包或者Chorme瀏覽器自帶的請(qǐng)求查看功能來查看POST請(qǐng)求提交的表單是怎樣的多律。Chorme按F12即可

re.png

輸入帳號(hào)密碼點(diǎn)擊登錄即可

re.png

點(diǎn)擊登陸后我們可以看到痴突,控制面板出現(xiàn)了一堆訪問的記錄搂蜓,第一個(gè)就是我們要找的,第一個(gè)的Status標(biāo)志是302辽装,302是重定向的意思帮碰。我們點(diǎn)擊(pass.asp)這個(gè)請(qǐng)求,然后查看它的POST的請(qǐng)求頭(點(diǎn)擊Headers)拾积。

re.png

我們看到了一堆的Set-Cookie字段殉挽,字段對(duì)應(yīng)的內(nèi)容就是我們要攜帶做GET請(qǐng)求的

re.png

同時(shí)我們可以看到POST提交的表單內(nèi)容,有些網(wǎng)站的提交參數(shù)是經(jīng)過加密的拓巧,如果要做通用的斯碌,我們需要找到它加密的方法,做同樣的加密處理肛度。

接下來使用OkHttp進(jìn)行操作
由于OkHttp提供了自動(dòng)攜帶Cookie進(jìn)行請(qǐng)求的功能傻唾,于是我們可以很方便地進(jìn)行處理了。

final OkHttpClient client = new OkHttpClient().newBuilder()
                .followRedirects(false)  //禁制OkHttp的重定向操作承耿,我們自己處理重定向
                .followSslRedirects(false)
                .cookieJar(new LocalCookieJar())   //為OkHttp設(shè)置自動(dòng)攜帶Cookie的功能
                .build();

//CookieJar是用于保存Cookie的
class LocalCookieJar implements CookieJar{
    List<Cookie> cookies;
    @Override
    public List<Cookie> loadForRequest(HttpUrl arg0) {
         if (cookies != null)
                return cookies;
            return new ArrayList<Cookie>();
    }

    @Override
    public void saveFromResponse(HttpUrl arg0, List<Cookie> cookies) {
        this.cookies = cookies;
    }
    
}

為什么設(shè)置CookieJar就能自動(dòng)攜帶Cookie了呢冠骄?給你看一段OkHttp的源碼就知道了。

/**
   * Populates request with defaults and cookies.
   *
   * <p>This client doesn't specify a default {@code Accept} header because it doesn't know what
   * content types the application is interested in.
   */
  private Request networkRequest(Request request) throws IOException {
    Request.Builder result = request.newBuilder();

    //如果CookieJar的Cookie不為空加袋,則設(shè)置Cookie字段
    List<Cookie> cookies = client.cookieJar().loadForRequest(request.url());
    if (!cookies.isEmpty()) {
      result.header("Cookie", cookieHeader(cookies));
    }

    return result.build();
  }

于是接下來我們就是做POST請(qǐng)求了

        final OkHttpClient client = new OkHttpClient().newBuilder()
                .followRedirects(false)
                .followSslRedirects(false)
                .cookieJar(new LocalCookieJar())
                .build();
        //構(gòu)造一個(gè)POST請(qǐng)求
        RequestBody body = new FormBody.Builder().add("UserStyle", "student")
                .add("user", "xxx").add("password", "xxx").build();
                
        Request request = new Request.Builder().url("http://222.195.8.201/pass.asp").post(body).build();
        
        client.newCall(request).enqueue(new Callback() {
            
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                /**
                 * 如果不用CookieJar,那么就要自己去解析返回的Set-Cookie字段,解析之后通過addHeader("Cookie", cookie)
                 * 添加Cookie請(qǐng)求頭
                 */
//              List<String> cookies =  response.headers("Set-Cookie");
//              String cookie = "";
//              for(int i=cookies.size()-1; i>=0; i--){
//                  cookie = cookie+ cookies.get(i).replace("path=/", "") + " ";
//              }
                
                //做GET請(qǐng)求
                Request redirectRequest = new Request.Builder().url("http://222.195.8.201/student/asp/Select_Success.asp")
//                    .addHeader("Cookie", cookie)
                      .build();
                //拿到登陸后操作的某個(gè)網(wǎng)頁的內(nèi)容
                Response response2 = client.newCall(redirectRequest).execute();
                String result = response2.body().string();
                System.out.println(result);
            }
            
            @Override
            public void onFailure(Call arg0, IOException arg1) {
                
            }
        });

拿到內(nèi)容后就可以自己進(jìn)行內(nèi)容的解析和展示了猴抹。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市锁荔,隨后出現(xiàn)的幾起案子蟀给,更是在濱河造成了極大的恐慌,老刑警劉巖阳堕,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件跋理,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡恬总,警方通過查閱死者的電腦和手機(jī)前普,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來壹堰,“玉大人拭卿,你說我怎么就攤上這事〖溃” “怎么了峻厚?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)谆焊。 經(jīng)常有香客問我惠桃,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任辜王,我火速辦了婚禮劈狐,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘呐馆。我一直安慰自己肥缔,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布汹来。 她就那樣靜靜地躺著续膳,像睡著了一般。 火紅的嫁衣襯著肌膚如雪俗慈。 梳的紋絲不亂的頭發(fā)上姑宽,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音闺阱,去河邊找鬼炮车。 笑死,一個(gè)胖子當(dāng)著我的面吹牛酣溃,可吹牛的內(nèi)容都是我干的瘦穆。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼赊豌,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼扛或!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起碘饼,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤熙兔,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后艾恼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體住涉,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年钠绍,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了舆声。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡柳爽,死狀恐怖媳握,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情磷脯,我是刑警寧澤蛾找,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站争拐,受9級(jí)特大地震影響腋粥,放射性物質(zhì)發(fā)生泄漏晦雨。R本人自食惡果不足惜架曹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一隘冲、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧绑雄,春花似錦展辞、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至脚粟,卻和暖如春覆旱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背核无。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來泰國打工扣唱, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人团南。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓噪沙,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親吐根。 傳聞我的和親對(duì)象是個(gè)殘疾皇子正歼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)拷橘,斷路器局义,智...
    卡卡羅2017閱讀 134,659評(píng)論 18 139
  • http協(xié)議有http0.9,http1.0冗疮,http1.1和http2三個(gè)版本萄唇,但是現(xiàn)在瀏覽器使用的是htt...
    一現(xiàn)_閱讀 1,864評(píng)論 0 3
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,162評(píng)論 25 707
  • “關(guān)你什么事穷绵?干嘛去做那些本來不需要你做的事情啊特愿?不要自討苦吃仲墨!” “自己的事情已經(jīng)夠多了,為什么還要惹麻煩上身揍障?...
    婉玲閱讀 2,309評(píng)論 2 0
  • 山間的森林里 溪水在流淌 溪水忘記了時(shí)間 因?yàn)樗蜁r(shí)間融為了一體 時(shí)間就是它 它就是時(shí)間 山里唯一的鬧鐘 是麻雀清...
    李碩小叔閱讀 148評(píng)論 0 0