2009-08-01 22 views
4

Dans le code suivant, j'ai vérifié que la connexion à une URL depuis une applet préserve la session du navigateur si la classe URLConnection du JDK est utilisée. Cependant, ce n'est pas le cas si la bibliothèque HttpClient d'Apache est utilisée. Quelqu'un sait-il pourquoi? Sinon, existe-t-il un moyen pour moi de définir l'instance de connexion à utiliser par une instance HttpClient?Connexion à une URL à partir d'une applet utilisant HttpClient d'Apache vs utilisation URLConnection du JDK

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(); 
     } 
    } 
} 
+0

Je l'ai essayé, et mon applet ne partage pas implicitement la session du navigateur. Est-ce que cela fonctionne en 2012? J'ai préféré passer l'ID de session en tant que ' 'à la place, et définir explicitement un cookie avec cette valeur. –

Répondre

3

Ceci est un problème courant avec les bibliothèques implémentant leur propre connexion URL via Socket. Apparemment, l'implémentation JRE de la classe URLConnection peut accéder directement aux informations du navigateur. Nous avons dû employer la technique mentionnée par oscargm ci-dessus, c'est-à-dire sur le serveur d'applications écrivant la requête cookies pour être les paramètres de l'applet ET arriver aux cookies de document du navigateur en utilisant JavaScript (ceci est le cas de SSO où l'ensemble de cookies ne pas être le même en raison de l'agent intermédiaire - serveurs proxy). Notez que si les cookies sont HttpOnly - le code javascript échouera.

0

Les causes possibles, est que vous ne l'avez pas fait une déconnexion() lors de l'utilisation URLConnection, cependant, la bibliothèque apache fermera la connexion lorsque vous avez terminé avec elle.

+0

Je ne comprends pas. URLConnection se comporte comme prévu. Vous semblez avoir l'impression que j'ai des problèmes avec ça. –

+0

Je veux dire que le HTTPClient Apache se déconnecte et ainsi vous perdez vos informations de session. Et les connexions faites par la suite seront totalement nouvelles avec une nouvelle information de session. – Ram

+0

Le code de test montre clairement que j'utilise HttpClient une seule fois. Je devrais probablement avoir fourni le code de test côté serveur ainsi que la sortie qui montre comment j'ai conclu que cette utilisation unique de HttpClient a échoué. –

1

Je pense que vous utilisez une ancienne version de HttpClient. Découvrez HttpClient's website.

Dans l'API actuelle, vous pouvez utiliser HttpState dans la méthode d'exécution, de sorte que votre code pourrait ressembler à ceci:

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

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

Dans la prochaine exécution, passez le même objet « d'état », et vous Les informations d'identification et les cookies seront conservés.

+0

Si vous devez rester avec votre version de HttpClient, dites-moi ce que c'est - et peut-être qu'il y a un équivalent dans votre version. –

2

Vous devez envoyer le cookie jsessionid ou réécrire votre URL pour utiliser le jsessionid.

C'est ainsi que le serveur connaît votre session.

Si vous générez dynamiquement la balise applet dans une page JSP, vous pouvez passer la valeur jsessionid à l'applet en tant que paramètre, puis l'utiliser.

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

Thi est un problème important.

La classe standard java.net.URLConnection intègre de façon transparente avec le plugin Java et le navigateur Web, peut hériter de session, jetons d'authentification HTTP, connecteurs proxy, etc.

Les gars de Apache Commons a fait une grossière erreur lorsque ils ont décidé d'implémenter HttpClient à partir de Socket (c'est-à-dire, à partir de zéro) au lieu de simplement développer au-dessus des classes java.net.URL * standard. HttpClient n'hérite pas de java.net.URLConnection et ne peut donc pas hériter de ses fonctionnalités d'entreprise avancées. Peut-être que les projets OpenSource ne sont pas si intelligents qu'ils le pensent.

+2

Commentaires comme "Peut-être que les projets OpenSource ne sont pas aussi intelligents qu'ils le pensent." ne contribue pas vraiment à une réponse utile. –

+0

Je voudrais vous upvote si vous supprimez la dernière ligne. –

0

je pouvais le faire fonctionner sans cookies passer comme arguments de la page Web avec ce code:

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 classe de JDK peut heureusement obtenir les cookies de la boutique « système ». Dans ce cas, c'est le magasin du navigateur, accessible via le plugin Java.

Une sorte de "travail manuel", mais cela fonctionne.

NOTE: J'ai trouvé le code here