在Java中发布到HTTPS,奇怪的行为

时间:2017-12-11 18:39:32

标签: java php curl

我决定用Java发布一些东西,但却陷入了这样一个看似微不足道的任务。然后我感到沮丧,并在PHP中重写整个事情,它完美无缺。我尝试比较Java和PHP结果的输出,以及我注意到Curl设置 Content-Type:multipart / form-data; 而Java(正确?)将其设置为 application / x-www-form-urlencoded; 但这会触发 500内部服务器错误。这到底是怎么回事?

Java调试:

2017/12/11 19:10:36:236 EET [DEBUG] wire - http-outgoing-0 >> "POST /auth/register HTTP/1.1[\r][\n]"
2017/12/11 19:10:36:243 EET [DEBUG] wire - http-outgoing-0 >> "Cookie: XSRF-TOKEN=eyJpdiI6InJJRjdORWdzUVcwQVZMR2l2WnNHUWc9PSIsInZhbHVlIjoiZVFSc0V5MCtURFE4dTZHZGlwVXdna0VGMGZtNzh0aEF4eXJcL0ZcL3d6QWM4NVdJejJaeEptUDFcL0ZDeXBEOGlDMTltbEQ4cFg0c1wvK3h4Nkp3VEhJTmFRPT0iLCJtYWMiOiIzNmRjZGNmZGNmYTFkYTQzODQ2NjFkZWY3ZWVlZGJmNzBiNDFhNTQwNDU3ODAzMTA4MGNhYWRiY2VhNDU2ZmU2In0%3D;laravel_session=eyJpdiI6ImF3cGg2TUFvWm54b3J4Nml5NnlBYlE9PSIsInZhbHVlIjoiXC85ZzdJS2drRWxlWGExXC93bHFVNXRtTmFtTmcyblJ4cXY4eUhCY2toaWJGaFBcL2NjQllKekVrUWFvblhydWtSeHpySm4yWGlWbHE3Y3dXZjFxd3lXV3c9PSIsIm1hYyI6IjRlNGZiMjU4NDRmMWVjZjc1YzExYWM4ZjJlMTUyNzI0ZTY3NTAwYTUyZTdlNTdiZmQ2ZDg1NTk1OGE4OGQ3ZGMifQ%3D%3D[\r][\n]"
2017/12/11 19:10:36:243 EET [DEBUG] wire - http-outgoing-0 >> "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:57.0) Gecko/20100101 Firefox/57.0[\r][\n]"
2017/12/11 19:10:36:243 EET [DEBUG] wire - http-outgoing-0 >> "Accept: */*[\r][\n]"
2017/12/11 19:10:36:243 EET [DEBUG] wire - http-outgoing-0 >> "Content-Length: 146[\r][\n]"
2017/12/11 19:10:36:243 EET [DEBUG] wire - http-outgoing-0 >> "Content-Type: application/x-www-form-urlencoded; charset=UTF-8[\r][\n]"
2017/12/11 19:10:36:243 EET [DEBUG] wire - http-outgoing-0 >> "Host: xxx[\r][\n]"
2017/12/11 19:10:36:243 EET [DEBUG] wire - http-outgoing-0 >> "Connection: Keep-Alive[\r][\n]"
2017/12/11 19:10:36:243 EET [DEBUG] wire - http-outgoing-0 >> "Accept-Encoding: gzip,deflate[\r][\n]"
2017/12/11 19:10:36:243 EET [DEBUG] wire - http-outgoing-0 >> "[\r][\n]"
2017/12/11 19:10:36:244 EET [DEBUG] wire - http-outgoing-0 >> "username=jnfjkwejf&_token=ZTE8t5XDf2vmBcAWpSenELkEtqvhIp9FBSy0E1Ez&domain=xxx&password=qweqweqwe&password_confirmation=qweqweqwe&captcha=U8Aq3"
2017/12/11 19:10:36:319 EET [DEBUG] wire - http-outgoing-0 << "HTTP/1.1 500 Internal Server Error[\r][\n]"

Java代码:

HttpHost target = new HttpHost("xxx", 443, "https");
        SSLContext sslcontext = SSLContexts.createSystemDefault();
        SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(
                sslcontext, new String[] { "TLSv1.2", "SSLv3" }, null,
                SSLConnectionSocketFactory.getDefaultHostnameVerifier());

        Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.INSTANCE)
                .register("https", sslConnectionSocketFactory)
                .build();
    PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(socketFactoryRegistry);

    CloseableHttpClient httpsclient = HttpClients.custom()
            .setSSLSocketFactory(sslConnectionSocketFactory)
            .setConnectionManager(cm)
            .build();
    ArrayList<NameValuePair> formparams = new ArrayList<>();
    formparams.add(new BasicNameValuePair("username", "jnfjkwejf"));
    formparams.add(new BasicNameValuePair("_token", _token));
    formparams.add(new BasicNameValuePair("domain", "xxx"));
    formparams.add(new BasicNameValuePair("password", "qweqweqwe"));
    formparams.add(new BasicNameValuePair("password_confirmation", "qweqweqwe"));
    formparams.add(new BasicNameValuePair("captcha", captcha));
    UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, Consts.UTF_8);
    HttpPost httppost = new HttpPost("/auth/register");
    String fullCookie =
            captchaConn.getHeaderFields().get("Set-Cookie").get(1).split(";")[0] + ";" +
            captchaConn.getHeaderFields().get("Set-Cookie").get(0).split(";")[0];
    httppost.addHeader("Cookie", fullCookie);
    httppost.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:57.0) Gecko/20100101 Firefox/57.0");
    httppost.addHeader("Accept", "*/*");
    httppost.setEntity(entity);
    CloseableHttpResponse execute = httpsclient.execute(httppost);

PHP:

> POST /auth/register HTTP/1.1
Host: xxx
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:57.0) Gecko/20100101 Firefox/57.0
Accept: */*
Cookie: XSRF-TOKEN=eyJpdiI6Im4zSXNHanBpM1FmXC9oZ0dEeFZFbElRPT0iLCJ2YWx1ZSI6Inh2S2FKSktQMGFxREMwVU5KZHkzSVEzaXFyVnNWdEpiQ1IzVFd4Y3c3RWFxQXV6YXFRaFNuQlBSU2M5bEs5azh2dG9zSjFoQWlNVW00dGgzeW1IeFhRPT0iLCJtYWMiOiI4MTUwZTk3ZDNkZDMyOTkxMjRkNjRhY2I5MjEzMDZmNTk5NzUwYjA5NDY3YmY0OWQ4YzQ1NmMxNTVjZDIwNzNkIn0%3D; laravel_session=eyJpdiI6IldnbGd1STlUSVZXc0NFbWZLTVhGZEE9PSIsInZhbHVlIjoiRDBndzlSZFJLUlZHYWdJWmppZmNCOWRYV2liNnV1NFJkMzNoNEpyVGRBaXlEUm94MzNSbmZ4YVdDeHM0OTNNa21qZmQ1Tjd4UVJrK2pYS3BUQUhsbFE9PSIsIm1hYyI6ImZkNTBmZjYxOTc0ZmUxNzIzZTNlOTBkYWJmMzBkODhkODkxNTk1Mjc5Nzg5MTI5NmJkYzJlYzBjOTEyMGM0OTUifQ%3D%3D
Content-Length: 718
Expect: 100-continue
Content-Type: multipart/form-data; boundary=------------------------e939a893b45ae97c

< HTTP/1.1 100 Continue
< HTTP/1.1 302 Found
< Server: nginx/1.10.3
< Content-Type: text/html; charset=UTF-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< Cache-Control: no-cache
...

卷曲选项:

curl_setopt($ch, CURLOPT_URL, 'https://xxx/auth/register');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:57.0) Gecko/20100101 Firefox/57.0');
curl_setopt($ch, CURLOPT_COOKIEFILE, __DIR__ . '.\cookiejar');
curl_setopt($ch, CURLOPT_COOKIEJAR, __DIR__ . '.\cookiejar');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);

2 个答案:

答案 0 :(得分:5)

如果您的服务器期待Content-Type: multipart/form-data,那么您应该使用MultipartEntityBuilder而不是UrlEncodedFormEntity

您的实体创建代码可能类似于

HttpEntity entity = MultipartEntityBuilder
    .create()
    .addTextBody("username", "jnfjkwejf")
    .addTextBody("_token", _token)
    .addTextBody("domain", "xxx")
    .addTextBody("password", "qweqweqwe")
    .addTextBody("password_confirmation", "qweqweqwe")
    .addTextBody("captcha", captcha)
    .build();

请参阅此链接以获取更多详细信息。 Apache HttpClient making multipart form post

更新 - 还有一点。

在Java情况下,您的Cookie标头看起来不正确。 cookie对应该用分号和空格('; ')分隔。你的java案例中缺少空格。参考 - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cookie

答案 1 :(得分:2)

curl可以使用两种编码中的任何一种,就像php或java一样,只需要正确配置请求类型。

urlencoded是旧式的multipart是块上的新小子,java必须能够生成两者,或许找一个新的java例子?

另外,为什么不尝试自己构建实际请求并发送您需要发送的实际字节,方法是每个字节自己创建一个请求? 认为这是一个学习练习。

为了调试服务器发送500错误的原因,我建议您阅读服务器的源代码并阅读服务器的日志,它可能只是喜欢新的做事方式。

不过我喜欢旧方式,我喜欢简单。它过去很简单,一个POST请求,在我的日子里... 现在,新的方式,感觉浪费,字节太多,数据太少。