Conexión a una URL desde un applet usando HttpClient de Apache versus usando la conexión URLC de JDK

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

Pregunta

En el siguiente código, he verificado que conectarse a una URL desde un applet conserva la sesión del navegador si se usa la clase URLConnection de JDK. Sin embargo, este no es el caso si se usa la biblioteca HttpClient de Apache. ¿Alguien sabe por qué? Alternativamente, ¿hay alguna manera de configurar la instancia de conexión para que la use una instancia de 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();
        }
    }
}
¿Fue útil?

Solución

Este es un problema común con las bibliotecas que implementan su propia conexión URL a través de Socket. Aparentemente, la implementación JRE de la clase URLConnection puede acceder directamente a la información del navegador. Tuvimos que emplear la técnica mencionada anteriormente por oscargm, es decir, en el servidor de aplicaciones escribiendo las cookies de solicitud para que sean los parámetros del applet Y obteniendo las cookies de documentos del navegador usando JavaScript (esto es para el caso de SSO donde el conjunto de cookies puede no será lo mismo debido al agente intermedio: servidores proxy). Tenga en cuenta que si las cookies son HttpOnly, el código de JavaScript fallará.

Otros consejos

Debe enviar la cookie jsessionid o reescribir su URL para usar el jsessionid .

Así es como el servidor conoce su sesión.

Si genera dinámicamente la etiqueta applet en una página JSP, puede pasar el valor jsessionid al applet como parámetro y luego usarlo.

post.setHeader("Cookie", "jsessionid=" + jsessionidValue );

Creo que está utilizando una versión anterior de HttpClient. Consulte sitio web de HttpClient .

En la API actual, puede usar HttpState en el método de ejecución, para que su código se vea así:

HttpClient client = new HttpClient();
HttpMethod method = new PostMethod(url.toURI());
HttpState state = new HttpState();

client.executeMethod(HttpConfiguration.ANY_HOST_CONFIGURATION, method, state);

En la próxima ejecución, pase el mismo "estado" objeto, y obtendrá las credenciales y cookies conservadas.

Posibles causas, es que no ha desconectado () al usar URLConnection, sin embargo, la biblioteca apache cerrará la conexión cuando haya terminado con ella.

Esto es un tema importante.

La clase estándar java.net.URLConnection se integra perfectamente con el complemento java y el navegador web, puede heredar sesión, tokens de autenticación HTTP, conectores proxy, etc.

Los chicos de Apache Commons cometieron un grave error cuando decidieron implementar HttpClient desde Socket (es decir, desde cero) en lugar de simplemente desarrollarse por encima de las clases estándar java.net.URL *. HttpClient no hereda de java.net.URLConnection, por lo que no puede heredar sus funciones empresariales avanzadas.

Quizás los proyectos OpenSource no sean tan inteligentes como piensan.

Podría hacerlo funcionar sin pasar cookies como argumentos de la página web con este código:

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)));

La clase CookieHandler de JDK puede, afortunadamente, obtener las cookies del "sistema". almacenar. En este caso, es la tienda del navegador, a la que se accede a través del complemento de Java.

Una especie de " trabajo manual " ;, pero funciona.

NOTA: Encontré el código aquí

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top