我正在尝试使用java登录报告系统。到目前为止,我已经尝试了许多使用HttpURLConnection的不同实现。我试图发布的HTML归结为:
<form name="logonForm" method="POST" action="http://remoteserver/logon.object">
<input type="hidden" name="qryStr" value="">
<input type="hidden" name="cmsVisible" value="true">
<input type="hidden" name="authenticationVisible" value="true">
<input type="hidden" name="referer" value="">
<input type="hidden" name="refererFormData" value="">
<input type="hidden" name="isFromLogonPage" value="true">
<input type="text" name="cms" value="xxxxx" class="textfield" id="apsTextEdit">
<input type="text" name="username" value="xxxxx"class="textfield" id="usernameTextEdit">
<input type="text" name="password" value="xxxxx"class="textfield" id="passwordTextEdit">
<select name="authType"id="authenticationSelectBox">
<option selected value='xxxxx'>xxxxx</select>
<input type="submit" name="SUBMIT">
</form>
我知道这个表单提供了有效的输入,因为当我在浏览器中单击提交时,它会将我登录到我的报告系统中。但是,当我发送程序化请求时,我总是将上面的html作为响应返回。注意我已经尝试了大约一百万个使用HttpURLRequest的实现。一个例子:
OutputStreamWriter wr = new OutputStreamWriter(connection.getOutputStream());
wr.write(parameters);
wr.flush();
// Get the response
BufferedReader rd = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
String allLines = "";
while ((line = rd.readLine()) != null) {
allLines += "\n" + line; // Process line...
}
wr.close();
rd.close();
return allLines;
其中'参数'的范围从任何内容到我发布的HTML中的每个URL编码参数,并且连接(目前,正如我尝试过其他配置)设置如下:
connection = (HttpURLConnection) url.openConnection();
HttpURLConnection.setFollowRedirects(true);
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setRequestMethod("POST");
connection.setAllowUserInteraction(false);
connection.setRequestProperty("Content-type", "application/x-www-form-urlencoded; charset=" + "UTF-8");
connection.setUseCaches(false);
connection.connect();
我知道细节有点稀疏,所以如果您需要更多信息,请告诉我,非常感谢任何输入!
答案 0 :(得分:2)
您需要确保同时采用{{1}}对所有 name=value
元素以及您想要以编程方式“按”的<input type="hidden">
元素在查询字符串中。该按钮只有一个名称,但无论如何,您需要传递它。这样,服务器端可以区分是否按下按钮,如果是,则按哪一个。
此外,如果表单需要会话(它可能使用基于请求的令牌),那么您还需要自己维护cookie。检查并从第一个响应的标头中获取<input type="submit">
,并将其设置为后续请求的Set-Cookie
标头。
为了更简单,更简洁的HTTP /表单处理,请考虑Apache HttpComponents Client。
另见:
答案 1 :(得分:1)
在某些情况下,您的代码可能会陷入僵局。您应该在从输入读取之前关闭输出。在不关闭流的情况下,服务器不知道您的请求是否完整。
如果由于某种原因需要保持输出打开,则需要发送“内容长度”标题以通知服务器预期的数量。
必须正确编码参数。我通常会放入一张地图并将其序列化,
StringBuilder sb = new StringBuilder(baseUrl);
for (Parameter p : parameters) {
if (sb.length() > 0)
sb.append('&');
try {
sb.append(URLEncoder.encode(p.name, "UTF-8"));
if (p.value != null) {
sb.append('=');
sb.append(URLEncoder.encode(p.value, "UTF-8"));
}
} catch (UnsupportedEncodingException e) {
// Not really possible, throw unchecked exception
throw new IllegalStateException("No UTF-8");
}
}
确定要发布的参数的最佳方法是在浏览器中捕获发布的跟踪并查看浏览器如何执行此操作。 FireBug / DebugBar是你的朋友。