日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

本文介紹了通過反射訪問HttpURLConnection的私有MessageHeader字段(&Q;Autorization&Q;)的處理方法,對大家解決問題具有一定的參考價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧!

問題描述

目前正在為現(xiàn)有庫編寫單元測試,我正在嘗試解決here的限制,即您無法使用反射檢索已設(shè)置的授權(quán)和標(biāo)頭。

我使用的代碼是一個(gè)非常典型的代碼片段,我已經(jīng)使用了幾十次來訪問私有字段:

HttpURLConnection conn = (HttpURLConnection) new URL("https://stackoverflow.com").openConnection();
conn.setRequestProperty("Authorization", "Basic Zm9vYmFyOnNlY3JldA==");
try {
    Field requests = conn.getClass().getSuperclass().getSuperclass().getSuperclass().getDeclaredField("requests");
    requests.setAccessible(true);
    MessageHeader headers = (MessageHeader) requests.get(conn); // Problem: returns null
    return headers.getValue(headers.getKey("Authorization"));
} catch (IllegalAccessException | NoSuchFieldException e) {
    e.printStackTrace();
}

但是-通過Field::get提取失敗并返回null(請參閱注釋行)。

查看HttpUrlConnection的基類URLConnection,我知道我正在尋找requests字段。通過它調(diào)試,我可以看到我想要提取的字段(甚至顯示了授權(quán)和值):

在無法返回MessageHeader對象的代碼行中,看起來我引用了URLConnection

中的字段

但我肯定遺漏了什么–有人能說出是什么嗎?

更新

讓我困惑的是

    我只從java.net包導(dǎo)入URLConnectionHttpURLConnection這一事實(shí)。然而,從第一個(gè)調(diào)試屏幕截圖來看,conn-對象實(shí)現(xiàn)顯然來自sun.net.www.protocol.https
    DelegateHttpsURLConnection成員(也顯示在第一個(gè)調(diào)試截圖中)

推薦答案

當(dāng)您在對象上調(diào)用getClass()時(shí),您將獲得其實(shí)際的運(yùn)行時(shí)類型,該類型不必與編譯時(shí)類型匹配,因?yàn)樗赡苁撬淖宇悺R虼耍ㄟ^getSuperclass()遍歷類層次結(jié)構(gòu)是很脆弱的。

當(dāng)您知道預(yù)先聲明了字段的類時(shí),您可以只使用該類,例如

HttpURLConnection conn = (HttpURLConnection)
    new URL("https://stackoverflow.com").openConnection();
try {
  Field f = URLConnection.class.getDeclaredField("requests");
  f.setAccessible(true);
  System.out.println(f.get(conn));
}
catch(ReflectiveOperationException ex) {
  ex.printStackTrace();
}

但是,這將始終打印null,因?yàn)檫@個(gè)特定的連接實(shí)現(xiàn)不使用其超類狀態(tài),而是委托給不同的實(shí)現(xiàn)。正如您自己發(fā)現(xiàn)的那樣,它存儲在一個(gè)名為delegate的字段中。

HttpURLConnection conn = (HttpURLConnection)
    new URL("https://stackoverflow.com").openConnection();
for(Class<?> c = conn.getClass(); c != URLConnection.class; c = c.getSuperclass())
  System.out.print(c.getName() + " > ");
System.out.println(URLConnection.class.getName());

Field delegate = conn.getClass().getDeclaredField("delegate");
delegate.setAccessible(true);
conn = (HttpURLConnection)delegate.get(conn);

for(Class<?> c = conn.getClass(); c != URLConnection.class; c = c.getSuperclass())
  System.out.print(c.getName() + " > ");
System.out.println(URLConnection.class.getName());

Field requests = URLConnection.class.getDeclaredField("requests");
requests.setAccessible(true);
System.out.println(requests.get(conn));

此打印

sun.net.www.protocol.https.HttpsURLConnectionImpl > javax.net.ssl.HttpsURLConnection > java.net.HttpURLConnection > java.net.URLConnection
sun.net.www.protocol.https.DelegateHttpsURLConnection > sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection > sun.net.www.protocol.http.HttpURLConnection > java.net.HttpURLConnection > java.net.URLConnection
null

顯示這兩個(gè)對象具有不同的類層次結(jié)構(gòu),因此,假設(shè)特定深度遍歷它確實(shí)是脆弱的。

它還會再次打印null,因?yàn)榧词故沁@個(gè)實(shí)現(xiàn)類也沒有使用從URLConnection繼承的requests字段。相反,類sun.net.www.protocol.http.HttpURLConnection聲明了自己的同名字段,其中包含實(shí)際的MessageHeader對象。這就是為什么在委托的實(shí)現(xiàn)類上執(zhí)行getSuperclass().getSuperclass()會得到正確的字段,而不是URLConnection的字段。

當(dāng)我們事先知道這一點(diǎn)時(shí),我們可以使用

HttpURLConnection conn =
    (HttpURLConnection) new URL("https://stackoverflow.com").openConnection();
conn.setRequestProperty("Authorization", "Basic Zm9vYmFyOnNlY3JldA==");

Field delegate = Class.forName("sun.net.www.protocol.https.HttpsURLConnectionImpl")
    .getDeclaredField("delegate");
Field requests = Class.forName("sun.net.www.protocol.http.HttpURLConnection")
    .getDeclaredField("requests");
AccessibleObject.setAccessible(new Field[] { delegate, requests}, true);
sun.net.www.MessageHeader headers =
    (sun.net.www.MessageHeader)requests.get(delegate.get(conn));
return headers.findValue("Authorization");

因?yàn)槟鸁o論如何都要訪問sun.net. …包,所以您可以直接引用這些類,而不是使用Class.forName,但我認(rèn)為后者在這種特定情況下更可靠,因?yàn)樗羞@些類都很容易混淆名稱,有時(shí)甚至是相同的簡單名稱,只是它們的包不同。

private String getAuthorizationHeaderValue(HttpURLConnection conn) {
  try {
    Field delegate = sun.net.www.protocol.https.HttpsURLConnectionImpl.class.getDeclaredField("delegate");
    Field requests = sun.net.www.protocol.http.HttpURLConnection.class.getDeclaredField("requests");
    AccessibleObject.setAccessible(new Field[] { delegate, requests}, true);
    sun.net.www.MessageHeader headers = (sun.net.www.MessageHeader)requests.get(delegate.get(conn));
    return headers.findValue("Authorization");
  } catch(ReflectiveOperationException ex) {
    ex.printStackTrace();
    return "";
  }
}

這篇關(guān)于通過反射訪問HttpURLConnection的私有MessageHeader字段(&Q;Autorization&Q;)的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,

分享到:
標(biāo)簽:Autorization HttpURLConnection MessageHeader 反射 字段 私有 訪問
用戶無頭像

網(wǎng)友整理

注冊時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運(yùn)動步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績評定2018-06-03

通用課目體育訓(xùn)練成績評定