ApacheのHttpClientを使用した場合とJDKのURLConnectionを使用した場合のアプレット内からのURLへの接続
-
06-07-2019 - |
質問
次のコードでは、JDKのURLConnectionクラスが使用されている場合、アプレット内からURLに接続するとブラウザーのセッションが保持されることを確認しました。ただし、ApacheのHttpClientライブラリが使用されている場合、これは当てはまりません。誰が理由を知っていますか?あるいは、HttpClientインスタンスが使用する接続インスタンスを設定する方法はありますか?
import java.applet.Applet;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URISyntaxException;
import java.net.URL;
import javax.net.ssl.SSLException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
public class HttpClientTesterApplet extends Applet {
private static final long serialVersionUID = -1599714556710568947L;
public void testHttpClient() throws ClientProtocolException, IOException,
URISyntaxException {
URL url = new URL(String.format("%s://localhost:%s/%s/testHttpClient",
getParameter("protocol"), getParameter("port"),
getParameter("context")));
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(url.toURI());
System.out.println("Executing request " + post.getURI());
try {
System.out
.println(client.execute(post, new BasicResponseHandler()));
} catch (SSLException e) {
System.out.println(e.getMessage());
}
System.out.println("Executed request " + post.getURI());
System.out.println("Opening connection " + url);
HttpURLConnection urlConnection = (HttpURLConnection) url
.openConnection();
System.out.println("Opened connection " + url);
urlConnection.setRequestMethod("POST");
System.out.println("Connecting");
urlConnection.connect();
System.out.println("Connected");
InputStream inputStream = urlConnection.getInputStream();
try {
while (inputStream.read() != -1) {
System.out.println("Reading");
}
} finally {
inputStream.close();
}
}
}
解決
これは、Socketを介して独自のURL接続を実装するライブラリの一般的な問題です。どうやら、URLConnectionクラスのJRE実装は、ブラウザ情報に直接アクセスできます。上記のoscargmで述べた手法を使用する必要がありました。つまり、アプレットへのパラメーターとなるリクエストCookieを書き込むアプリサーバー上で、JavaScriptを使用してブラウザーのドキュメントCookieにアクセスする必要があります(CookieのセットがSSOの場合中間エージェント(プロキシサーバー)のため、同じではありません)。 CookieがHttpOnlyの場合、javascriptコードは失敗することに注意してください。
他のヒント
jsessionid
Cookieを送信するか、URLを書き換えて jsessionid
を使用する必要があります。
これがサーバーがセッションを認識する方法です。
JSPページで applet
タグを動的に生成する場合、 jsessionid
値をパラメータとしてアプレットに渡し、それを使用できます。
post.setHeader("Cookie", "jsessionid=" + jsessionidValue );
古いバージョンのHttpClientを使用していると思います。 HttpClientのWebサイトをご覧ください。
現在のAPIでは、executeメソッドでHttpStateを使用できるため、コードは次のようになります。
HttpClient client = new HttpClient();
HttpMethod method = new PostMethod(url.toURI());
HttpState state = new HttpState();
client.executeMethod(HttpConfiguration.ANY_HOST_CONFIGURATION, method, state);
次の実行では、同じ「状態」を渡しますオブジェクト、および保存された資格情報とCookieを取得します。
考えられる原因は、URLConnectionを使用するときにdisconnect()を実行していないことです。ただし、apacheライブラリは、終了時に接続を閉じます。
これは重要な問題です。
標準のjava.net.URLConnectionクラスは、javaプラグインおよびWebブラウザとシームレスに統合し、セッション、HTTP認証トークン、プロキシコネクタなどを継承できます。
Apache Commonsのスタッフは、標準のjava.net.URL *クラスの上で開発するのではなく、ソケットから(つまり、ゼロから)HttpClientを実装することに決めたときに大きな間違いを犯しました。 HttpClientはjava.net.URLConnectionを継承しないため、高度なエンタープライズ機能を継承できません。
オープンソースプロジェクトは、彼らが考えるほど賢くないかもしれません。
このコードを使用すると、WebページからCookieを引数として渡さずに動作させることができます。
private String retrieveCookies(URL url) throws IOException, URISyntaxException
{
String cookieValue = null;
CookieHandler handler = CookieHandler.getDefault();
if (handler != null) {
Map<String, List<String>> headers = handler.get(url.toURI(), new HashMap<String, List<String>>());
List<String> cookiesList = headers.get("Cookie");
if (cookiesList != null)
{
for (String v : cookiesList) {
if (cookieValue == null)
cookieValue = v;
else
cookieValue = cookieValue + ";" + v;
}
}
}
return cookieValue;
}
...
httppost.addHeader("Cookie", retrieveCookies(new URL(uploadUrl)));
JDKのクラスCookieHandlerは、幸運にも&quot; system&quot;からcookieを取得できます。格納。この場合、Javaプラグインを介してアクセスするブラウザストアです。
「手動作業」のソートですが、動作します。