简体   繁体   English

使用Apache的HttpClient与使用JDK的URLConnection的applet中的URL连接

[英]Connection to a URL from within an applet using Apache's HttpClient vs using the JDK's URLConnection

In the following code, I have verified that connecting to a URL from within an applet preserves the browser's session if JDK's URLConnection class is used. 在下面的代码中,我已经验证了如果使用JDK的URLConnection类,从applet中连接到URL会保留浏览器的会话。 However, this is not the case if Apache's HttpClient library is used. 但是,如果使用Apache的HttpClient库,则情况并非如此。 Does anyone know why? 有谁知道为什么? Alternatively, is there a way for me to set the connection instance to be used by an HttpClient instance? 或者,有没有办法让我设置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();
        }
    }
}

This is a common problem with libraries implementing their own URL connection via Socket. 这是库通过Socket实现自己的URL连接的常见问题。 Apparently, the JRE implementation of the URLConnection class can get to the browser information directly. 显然,URLConnection类的JRE实现可以直接获取浏览器信息。 We had to employ the technique as mentioned by oscargm above, ie on the appserver writing the request cookies to be the parameters to the applet AND getting to the browser's document cookies using JavaScript (this is for the case of SSO where the set of cookies may not be the same because of the intermediate agent -- proxy servers). 我们必须使用上面oscargm提到的技术,即在appserver上写请求cookie作为applet的参数并使用JavaScript获取浏览器的文档cookie(这适用于SSO的情况,其中cookie集可能因为中间代理 - 代理服务器而不一样。 Note that if the cookies are HttpOnly -- the javascript code will fail. 请注意,如果cookie是HttpOnly - javascript代码将失败。

You must send the jsessionid cookie or rewrite your URL to use the jsessionid . 您必须发送jsessionid cookie或重写您的URL才能使用jsessionid

That's the way the server knows your session. 这就是服务器知道你的会话的方式。

If you generate the applet tag in a JSP page dynamically you can pass the jsessionid value to the applet as a parameter and then use it. 如果您在JSP页面中动态生成applet标记,则可以将jsessionid值作为参数传递给applet,然后使用它。

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

I think that you're using an older version of HttpClient. 我认为您使用的是较旧版本的HttpClient。 Check out HttpClient's website . 查看HttpClient的网站

In the current API, you can use HttpState in the execute method, so that your code could look like this: 在当前的API中,您可以在execute方法中使用HttpState,这样您的代码可能如下所示:

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

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

In the next execution, pass the same "state" object, and you'll get the credentials and cookies preserved. 在下一次执行中,传递相同的“状态”对象,您将获得保留的凭据和cookie。

可能的原因是,在使用URLConnection时您没有执行disconnect(),但是,当您完成连接时,apache库将关闭连接。

Thi is an important issue. 这是一个重要问题。

The standard java.net.URLConnection class integrates seamlessly with the java plugin and the web browser, can inherit session, HTTP authentication tokens, proxy connectors, etc. 标准的java.net.URLConnection类与java插件和Web浏览器无缝集成,可以继承会话,HTTP身份验证令牌,代理连接器等。

The guys at Apache Commons made a gross mistake when they decided to implement HttpClient from Socket (ie, from scratch) instead of just developing on top of the standard java.net.URL* classes. 当他们决定从Socket实现HttpClient(即从头开始)而不是仅仅在标准java.net.URL *类之上进行开发时,Apache Commons的人员犯了一个大错。 HttpClient does not inherit from java.net.URLConnection so it cannot inherit its advanced enterprise features. HttpClient不从java.net.URLConnection继承,因此无法继承其高级企业功能。

Maybe OpenSource projects are not so smart as they think. 也许OpenSource项目并不像他们想象的那么聪明。

I could make it work without passing cookies as arguments from the Web Page with this code: 我可以使用以下代码从网页传递cookie作为参数使其工作:

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

JDK's class CookieHandler can fortunately get the cookies from the "system" store. JDK的类CookieHandler可以幸运地从“系统”商店获取cookie。 In this case it's the browser store, accesed via the Java Plugin. 在这种情况下,它是浏览器商店,通过Java插件加入。

Sort of "manual work", but it works. 一种“手工作业”,但它的工作原理。

NOTE: I found the code here 注意:我在这里找到了代码

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM