【问题标题】:How can post data to form which is in other server如何将数据发布到其他服务器中的表单
【发布时间】:2012-07-23 08:33:49
【问题描述】:

我正在创建自动化系统以将数据发布到表单以注册到网站

    URL url = new URL("https://www.walmart.com/subflow/YourAccountLoginContext/1471476370/sub_generic_login/create_account.do");
String postData = "firstName="+xlsDataList.get(0)+"&lastName="+xlsDataList.get(1)+"&userName="+xlsDataList.get(2)+"&userNameConfirm="+xlsDataList.get(3)+"&pwd="+xlsDataList.get(5)+"&pwdConfirm="+xlsDataList.get(6);
HttpsURLConnection  uc = (HttpsURLConnection) url.openConnection();
uc.setDoInput(true);
uc.setDoOutput(true);
uc.setRequestMethod("POST");
uc.setRequestProperty("Accept", "*/*");
uc.setRequestProperty("Content-Length", Integer.toString(postData.getBytes().length));
uc.setRequestProperty("Content-Type", "text/html; charset=utf-8");
OutputStreamWriter outputWriter = new OutputStreamWriter(uc.getOutputStream());
outputWriter.write(postData);
outputWriter.flush();
outputWriter.close(); 

我认为上面那些 postdata 只是请求属性,并进行了相应的编码。但是在仔细检查了视图源之后,我才知道这些是表单属性。 我无权访问该表格。现在我怎样才能将数据发布到表单,以便用户被网站注册?

我必须将值设置为 formbean。 请提供您的建议。

【问题讨论】:

  • 运行此代码时得到什么响应?
  • 做一件事。安装Firebug。你需要Firefox。现在从浏览器提交该表单并观察网络流量。寻找帖子请求。这将使您了解提交到服务器的所有字段。

标签: java https forms http-post


【解决方案1】:

您在 POST 中使用了错误的 Content-Type:您需要使用 application/x-www-form-urlencoded。更改后,服务器会将您的请求正文解释为请求参数,并且(可能)您的“formbean”将填充数据。

上面的代码可能是一个测试用例,但您确实应该注意正确编码您尝试发布的所有数据。否则,您将面临语法无效请求(在这种情况下,服务器将拒绝请求或忽略重要参数)或引入安全漏洞,用户可以将任意请求参数注入您的 POST 的风险。我强烈推荐如下代码:

import java.net.URLEncoder;

String charset = "UTF-8"; // Change this if you want some other encoding
StringBuilder postData = new StringBuilder();
postData.append(URLEncoder.encode("firstName", charset));
postData.append("=");
postData.append(URLEncoder.encode(xlsDataList.get(0)), charset);
postData.append("&");
postData.append(URLEncoder.encode("lastName", charset));
postData.append("=");
postData.append(URLEncoder.encode(xlsDataList.get(1), charset));
postData.append("&");
postData.append(URLEncoder.encode("userName", charset));
postData.append("=");
postData.append(URLEncoder.encode(xlsDataList.get(2), charset));
postData.append("&");
postData.append(URLEncoder.encode("userNameConfirm", charset));
postData.append("=");
postData.append(URLEncoder.encode(xlsDataList.get(3), charset));
postData.append("&");
postData.append(URLEncoder.encode("pwd", charset));
postData.append("=");
postData.append(URLEncoder.encode(xlsDataList.get(5), charset));
postData.append("&");
postData.append(URLEncoder.encode("pwdConfirm", charset));
postData.append("=");
postData.append(xlsDataList.get(6), charset));

对像“userNameConfirm”这样的静态字符串进行编码似乎很愚蠢,但如果你养成这种习惯,你最终会一直使用它,你的代码会更安全。

此外,您需要确保您通过OutputStream 发送的数据具有正确的Content-Length:您正在正确计算内容长度,但是您没有使用您用于计算发送到客户端的字节。您希望您的代码看起来更像这样:

byte[] postDataBytes = postData.getBytes(charset);
uc.setRequestProperty("Content-Length", Integer.toString(postDataBytes.length));
uc.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
OutputStream outputStream = uc.getOutputStream();
outputStream.write(postDataBytes);
outputStream.flush();
outputStream.close();

您可以在社区 wiki 中找到非常全面的 HTTPUrlConnection 教程:Using java.net.URLConnection to fire and handle HTTP requests

【讨论】:

  • 也许将 postData.append("&"); 替换为 postData.append("&"); 以使其完美。
  • @e-sushi '&' 和 '=' 明确允许在 x-www-form-urlencoded 中作为分隔符,不应转义。还有,“&”是一个 XML 实体,它是一种错误的 URL 编码编码; URL 编码使用百分比编码的十六进制数字。
  • @Alex 哎呀,你是对的。我忘记了 RFC 3986 的细节。我的错,对不起。但不会因为非法访问尝试而改变他的错误 500 问题。 ;)
【解决方案2】:

我推荐使用 Apache HttpClient。它更快更容易实现。

PostMethod post = new PostMethod("https://www.walmart.com/subflow/YourAccountLoginContext/1471476370/sub_generic_login/create_account.do");
    NameValuePair[] data = {
      new NameValuePair("firstName", "joe"),
      new NameValuePair("lastName", "bloggs")
    };
    post.setRequestBody(data);
    InputStream in = post.getResponseBodyAsStream();
    // handle response.

详情可以参考http://hc.apache.org/

【讨论】:

  • 您确定将这些值设置为 formbean?
【解决方案3】:

如果您的项目使用 Spring 3.x 或更高版本,我建议您使用 Spring RestTemplate,它对执行 http 非常方便,下面的代码将记录做一个表单发布。

public String login(String username, String password)
    {
        MultiValueMap<String, String> form = new LinkedMultiValueMap<>();
        form.add(usernameInputFieldName, username);
        form.add(passwordInputFieldName, password);
            RestTemplate template = new RestTemplate(); 
        URI location = template.postForLocation(loginUrl(), form);
        return location.toString();
    }

【讨论】:

    【解决方案4】:

    您在评论中描述的“HTTP 错误 500”是“内部服务器错误”。

    这意味着服务器要么无法使用您的请求 (GET/POST),要么存在特定于您尝试调用的服务器的问题。

    查看你调用的 URL,我立即出现同样的错误 500。

    在 httqs://www.walmart.com/subflow/YourAccountLoginContext/1471476370/sub_generic_login/create_account.do 上的 GET 和 POST 请求都会发生同样的情况(实时链接已停用;将“q”替换为“p”以使其正常工作.)

    简而言之:WallMart 服务器通常返回的“HTTP 错误 500”会阻止您的调用成功。

    顺便说一句:

    如果他们锁定了您的访问权限,则收到错误 500 而不是 403 的情况并不少见。

    由于您可能不拥有 WallMart 网站,并且您正在尝试访问其网站的值得保护免受 3rd 方访问的级别,因此很可能就是这种情况。 ;)

    PS:我不确定像这样在公共场合显示 AccountLogin 号码是否明智。毕竟,它是特定 WallMart 帐户持有人的客户 ID。但是,嘿,这是你的选择,不是我的。

    【讨论】:

      【解决方案5】:

      另外,请仔细检查您发送的参数。服务器正在对输入数据进行一些验证。例如,有些字段是必填的,有些只是数字,等等。

      【讨论】:

        【解决方案6】:

        尝试通过修改用户代理来欺骗浏览器。沃尔玛可能有一种安全机制,可以自动检测到您正在执行此操作。

        (如果您在设置用户代理时遇到问题,请参阅此帖子:Setting user agent of a java URLConnection

        【讨论】:

          猜你喜欢
          • 2016-04-14
          • 1970-01-01
          • 2020-06-14
          • 1970-01-01
          • 2019-03-31
          • 1970-01-01
          • 2021-02-19
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多