Connessione a un URL dall'interno di un'applet usando HttpClient di Apache vs usando URLConnection di JDK

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

Domanda

Nel seguente codice, ho verificato che la connessione a un URL dall'interno di un'applet conserva la sessione del browser se viene utilizzata la classe URLConnection di JDK. Tuttavia, questo non è il caso se viene utilizzata la libreria HttpClient di Apache. Qualcuno sa perché? In alternativa, esiste un modo per impostare l'istanza di connessione da utilizzare da un'istanza 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();
        }
    }
}
È stato utile?

Soluzione

Questo è un problema comune con le librerie che implementano la propria connessione URL tramite Socket. Apparentemente, l'implementazione JRE della classe URLConnection può accedere direttamente alle informazioni del browser. Abbiamo dovuto utilizzare la tecnica come menzionato da oscargm sopra, cioè sull'apperver scrivendo i cookie di richiesta come parametri nell'applet E arrivando ai cookie di documento del browser usando JavaScript (questo è il caso di SSO in cui l'insieme di cookie può non essere lo stesso a causa dell'agente intermedio - server proxy). Se i cookie sono HttpOnly, il codice javascript non funzionerà.

Altri suggerimenti

Devi inviare il jsessionid o riscrivere il tuo URL per utilizzare il jsessionid .

Questo è il modo in cui il server conosce la tua sessione.

Se si genera il tag applet in una pagina JSP in modo dinamico, è possibile passare il valore jsessionid all'applet come parametro e quindi utilizzarlo.

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

Penso che tu stia utilizzando una versione precedente di HttpClient. Scopri sito web di HttpClient .

Nell'API corrente, è possibile utilizzare HttpState nel metodo execute, in modo che il codice possa apparire così:

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

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

Nella prossima esecuzione, passa lo stesso " stato " oggetto e otterrai le credenziali e i cookie conservati.

Possibili cause, è che non hai fatto disconnect () quando usi URLConnection, tuttavia, la libreria apache chiuderà la connessione quando hai finito con essa.

Questo è un problema importante.

La classe standard java.net.URLConnection si integra perfettamente con il plug-in Java e il browser Web, può ereditare sessione, token di autenticazione HTTP, connettori proxy, ecc.

I ragazzi di Apache Commons hanno commesso un grave errore quando hanno deciso di implementare HttpClient da Socket (ovvero da zero) invece di svilupparsi solo in cima alle classi standard java.net.URL *. HttpClient non eredita da java.net.URLConnection, quindi non può ereditare le sue funzionalità aziendali avanzate.

Forse i progetti OpenSource non sono così intelligenti come pensano.

Potrei farlo funzionare senza passare i cookie come argomenti dalla Pagina Web con questo codice:

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 di classe JDK può fortunatamente ottenere i cookie dal "sistema" memorizzare. In questo caso è l'archivio del browser, accessibile tramite il plugin Java.

Ordinamento di " lavoro manuale " ;, ma funziona.

NOTA: ho trovato il codice qui

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top