使用 Apache 的 HttpClient 与使用 JDK 的 URLConnection 从小程序内连接到 URL

发布于 2024-07-29 18:57:48 字数 2172 浏览 8 评论 0原文

在下面的代码中,我已经验证,如果使用 JDK 的 URLConnection 类,则从小程序内连接到 URL 会保留浏览器的会话。 但是,如果使用 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();
        }
    }
}

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. However, this is not the case if Apache's HttpClient library is used. Does anyone know why? Alternatively, is there a way for me to set the connection instance to be used by an HttpClient instance?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

も星光 2024-08-05 18:57:48

这是通过 Socket 实现自己的 URL 连接的库的常见问题。 显然,URLConnection类的JRE实现可以直接获取浏览器信息。 我们必须采用上面 oscargm 提到的技术,即在应用程序服务器上将请求 cookie 写入小程序的参数,并使用 JavaScript 获取浏览器的文档 cookie(这是针对 SSO 的情况,其中 cookie 集可以由于中间代理(代理服务器)的原因,情况会有所不同。 请注意,如果 cookie 是 HttpOnly,则 javascript 代码将会失败。

This is a common problem with libraries implementing their own URL connection via Socket. Apparently, the JRE implementation of the URLConnection class can get to the browser information directly. We had to employ the technique as mentioned by oscargm above, i.e. 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). Note that if the cookies are HttpOnly -- the javascript code will fail.

天煞孤星 2024-08-05 18:57:48

您必须发送 jsessionid cookie 或重写您的 URL 以使用 jsessionid

这就是服务器了解您的会话的方式。

如果您在 JSP 页面中动态生成 applet 标记,则可以将 jsessionid 值作为参数传递给 applet,然后使用它。

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

You must send the jsessionid cookie or rewrite your URL to use the 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 jsessionidvalue to the applet as a parameter and then use it.

post.setHeader("Cookie", "jsessionid=" + jsessionidValue );
埋葬我深情 2024-08-05 18:57:48

我认为您使用的是旧版本的 HttpClient。 查看 HttpClient 的网站

在当前的 API 中,您可以在执行方法中使用 HttpState,这样您的代码可能如下所示:

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

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

在下一次执行中,传递相同的“状态”对象,您将获得保留的凭据和 cookie。

I think that you're using an older version of HttpClient. Check out HttpClient's website.

In the current API, you can use HttpState in the execute method, so that your code could look like this:

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.

一直在等你来 2024-08-05 18:57:48

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

Possible causes, is that you have not done a disconnect() when using URLConnection, however, the apache library will close the connection when you are done with it.

花间憩 2024-08-05 18:57:48

这是一个重要的问题。

标准的 java.net.URLConnection 类与 java 插件和 Web 浏览器无缝集成,可以继承会话、HTTP 身份验证令牌、代理连接器等。

Apache Commons 的人员在决定从 Socket 实现 HttpClient 时犯了一个严重错误(即,从头开始),而不是仅仅在标准 java.net.URL* 类之上进行开发。 HttpClient 不继承自 java.net.URLConnection,因此它无法继承其高级企业功能。

也许开源项目并不像他们想象的那么聪明。

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.

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. HttpClient does not inherit from java.net.URLConnection so it cannot inherit its advanced enterprise features.

Maybe OpenSource projects are not so smart as they think.

风吹雨成花 2024-08-05 18:57:48

我可以使用以下代码使其工作,而无需将 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 的 CookieHandler 类可以从“系统”存储中获取 cookie。 在本例中,它是浏览器商店,可通过 Java 插件访问。

有点像“手工工作”,但它确实有效。

注意:我在此处找到了代码

I could make it work without passing cookies as arguments from the Web Page with this 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)));

JDK's class CookieHandler can fortunately get the cookies from the "system" store. In this case it's the browser store, accesed via the Java Plugin.

Sort of "manual work", but it works.

NOTE: I found the code here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文