在下面的代码中,我已经验证了如果使用JDK的URLConnection类,从applet中连接到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();
}
}
}
答案 0 :(得分:3)
这是库通过Socket实现自己的URL连接的常见问题。显然,URLConnection类的JRE实现可以直接获取浏览器信息。我们必须使用上面oscargm提到的技术,即在appserver上写请求cookie作为applet的参数并使用JavaScript获取浏览器的文档cookie(这适用于SSO的情况,其中cookie集可能因为中间代理 - 代理服务器而不一样。请注意,如果cookie是HttpOnly - javascript代码将失败。
答案 1 :(得分:2)
您必须发送jsessionid
Cookie或重写您的网址才能使用jsessionid
。
这就是服务器知道你的会话的方式。
如果您在JSP页面中动态生成applet
标记,则可以将jsessionid
值作为参数传递给applet,然后使用它。
post.setHeader("Cookie", "jsessionid=" + jsessionidValue );
答案 2 :(得分:1)
我认为您使用的是较旧版本的HttpClient。查看HttpClient's website。
在当前的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);
在下一次执行中,传递相同的“状态”对象,您将保留凭据和cookie。
答案 3 :(得分:0)
可能的原因是,在使用URLConnection时你没有使用disconnect(),但是,当你完成连接时,apache库会关闭连接。
答案 4 :(得分:0)
这是一个重要的问题。
标准java.net.URLConnection类与java插件和Web浏览器无缝集成,可以继承会话,HTTP身份验证令牌,代理连接器等。
当他们决定从Socket实现HttpClient(即从头开始)而不是仅仅在标准的java.net.URL *类之上进行开发时,Apache Commons的人们犯了一个大错。 HttpClient不继承自java.net.URLConnection,因此无法继承其高级企业功能。
也许OpenSource项目并不像他们想象的那么聪明。
答案 5 :(得分:0)
我可以使用以下代码从网页传递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插件加入。
“手工作业”的排序,但它确实有效。
注意:我找到了代码here