1

我正在尝试使用 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();

我知道细节有点稀疏,所以如果您需要更多信息,请告诉我,非常感谢您的任何意见!

4

2 回答 2

2

您需要确保您还采用了所有元素name=value对以及您希望以编程方式在查询字符串中“按下”的元素对。该按钮只有一个名称,但无论如何,您都需要传递它。这样,服务器端可以区分是否按下了按钮,如果按下了,是哪个按钮。 <input type="hidden"><input type="submit">

此外,如果表单需要会话(它可能使用基于请求的令牌),那么您还需要自己维护 cookie。检查并Set-Cookie从第一个响应的标头中获取,并将其设置为Cookie后续请求的标头。

为了更轻松、更简洁地处理 HTTP/表单,请考虑使用Apache HttpComponents Client

也可以看看:

于 2010-06-22T13:11:44.793 回答
1

在某些情况下,您的代码可能会死锁。在读取输入之前,您应该关闭输出。如果不关闭流,服务器不知道您的请求已完成。

如果出于某种原因需要保持输出打开,则需要发送“Content-length”标头以通知服务器期望多少。

参数必须正确编码。我通常会放入一张地图并像这样序列化它,

            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 是你的朋友。

于 2010-06-22T14:25:06.807 回答