Соединение с URL из апплета с использованием HttpClient Apache против использования URLConnection JDK

StackOverflow https://stackoverflow.com/questions/1216165

Вопрос

В следующем коде я проверил, что подключение к 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.

В некотором роде «ручная работа», но это работает.

ПРИМЕЧАНИЕ. Я обнаружил код здесь

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top