Соединение с URL из апплета с использованием HttpClient Apache против использования URLConnection JDK
-
06-07-2019 - |
Вопрос
В следующем коде я проверил, что подключение к URL-адресу из апплета сохраняет сеанс браузера, если используется класс UDLConnection JDK. Однако это не тот случай, если используется библиотека 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();
}
}
}
Решение
Это распространенная проблема библиотек, реализующих собственное URL-соединение через Socket. По-видимому, реализация JRE класса URLConnection может напрямую получать информацию о браузере. Нам пришлось использовать технику, как указано выше в oscargm, то есть на сервере приложений, записывающем файлы cookie запроса в качестве параметров для апплета и получающем файлы cookie браузера с использованием JavaScript (это для случая единого входа, когда набор файлов cookie может не будет одинаковым из-за промежуточного агента - прокси-серверов). Обратите внимание, что если файлы cookie являются HttpOnly - код JavaScript не будет работать.
Другие советы
Вы должны отправить файл cookie jsessionid
или переписать свой URL, чтобы использовать jsessionid
.
Именно так сервер знает ваш сеанс.
Если вы динамически генерируете тег applet
на странице JSP, вы можете передать значение jsessionid
апплету в качестве параметра, а затем использовать его.
post.setHeader("Cookie", "jsessionid=" + jsessionidValue );
Я думаю, что вы используете старую версию HttpClient. Посетите веб-сайт HttpClient . Р>
В текущем API вы можете использовать HttpState в методе execute, чтобы ваш код мог выглядеть следующим образом:
HttpClient client = new HttpClient();
HttpMethod method = new PostMethod(url.toURI());
HttpState state = new HttpState();
client.executeMethod(HttpConfiguration.ANY_HOST_CONFIGURATION, method, state);
В следующем выполнении передайте то же самое «состояние» объект, и вы получите сохраненные учетные данные и файлы cookie.
Возможные причины: вы не отключили () при использовании URLConnection, однако библиотека apache закроет соединение, когда вы закончите с ним.
Это важная проблема.
Стандартный класс java.net.URLConnection легко интегрируется с плагином java и веб-браузером, может наследовать сеанс, токены HTTP-аутентификации, прокси-коннекторы и т. д.
Ребята из Apache Commons допустили грубую ошибку, когда решили внедрить HttpClient из Socket (то есть с нуля) вместо того, чтобы просто разрабатывать поверх стандартных классов java.net.URL *. HttpClient не наследуется от java.net.URLConnection, поэтому он не может наследовать свои расширенные корпоративные функции.
Может быть, проекты OpenSource не так умны, как они думают.
Я мог бы заставить его работать, не передавая куки в качестве аргументов с веб-страницы с этим кодом:
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)));
CookieHandler класса JDK, к счастью, может получить файлы cookie из " системы " хранить. В данном случае это магазин браузера, доступ к которому осуществляется через плагин Java.
В некотором роде «ручная работа», но это работает.
ПРИМЕЧАНИЕ. Я обнаружил код здесь