【问题标题】:https URL is working fine with curl but not with Javahttps URL 在 curl 上运行良好,但在 Java 上却不行
【发布时间】:2012-07-08 12:38:39
【问题描述】:

我正在尝试使用 java 将数据发布到服务器到此 url:

https:www.stackoverflow.com

它没有更新数据。

但是当我尝试使用 curl 进行相同操作时,它会使用此 url 更新数据:

E:\curl ssl>curl -k -X POST -u"user:pass" "www.stackoverflow.com" 

编辑:

public void authenticatePostUrl() {

        HostnameVerifier hv = new HostnameVerifier() {

            @Override
            public boolean verify(String urlHostName, SSLSession session) {
                System.out.println("Warning: URL Host: " + urlHostName
                        + " vs. " + session.getPeerHost());
                return true;
            }
        };
        // Now you are telling the JRE to trust any https server.
        // If you know the URL that you are connecting to then this should
        // not be a problem
        try {
            trustAllHttpsCertificates();
        } catch (Exception e) {
            System.out.println("Trustall" + e.getStackTrace());
        }
        HttpsURLConnection.setDefaultHostnameVerifier(hv);
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        try {
            URL url = new URL("www.stackoverflow.com");

            String credentials = "user" + ":" + "password";
            String encoding = Base64Converter.encode(credentials.getBytes("UTF-8"));
            HttpsURLConnection  uc = (HttpsURLConnection) url.openConnection();
            uc.setDoInput(true); 
            uc.setDoOutput(true);
            uc.setRequestProperty("Authorization", String.format("Basic %s", encoding));
            uc.setRequestMethod("POST");
            uc.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
            uc.setRequestProperty("Accept", "application/x-www-form-urlencoded; charset=utf-8");
            uc.getInputStream();
            System.out.println(uc.getContentType());
            InputStream content = (InputStream) uc.getInputStream();
            BufferedReader in = new BufferedReader(new InputStreamReader(
                    content));
            String line;
            while ((line = in.readLine()) != null) {
                pw.println(line);
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
            pw.println("Invalid URL");
        } catch (IOException e) {
            e.printStackTrace();
            pw.println("Error reading URL");
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(sw.toString());
    }


    public static void main(String[] args) {
        // TODO Auto-generated method stub
        CurlAuthentication au = new CurlAuthentication();
        au.authenticatePostUrl();
        au.authenticateUrl();
    }

    // Just add these two functions in your program

    public static class TempTrustedManager implements
            javax.net.ssl.TrustManager, javax.net.ssl.X509TrustManager {
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        public boolean isServerTrusted(
                java.security.cert.X509Certificate[] certs) {
            return true;
        }

        public boolean isClientTrusted(
                java.security.cert.X509Certificate[] certs) {
            return true;
        }

        public void checkServerTrusted(
                java.security.cert.X509Certificate[] certs, String authType)
                throws java.security.cert.CertificateException {
            return;
        }

        public void checkClientTrusted(
                java.security.cert.X509Certificate[] certs, String authType)
                throws java.security.cert.CertificateException {
            return;
        }
    }

    private static void trustAllHttpsCertificates() throws Exception {

        // Create a trust manager that does not validate certificate chains:

        javax.net.ssl.TrustManager[] trustAllCerts =

        new javax.net.ssl.TrustManager[1];

        javax.net.ssl.TrustManager tm = new TempTrustedManager();

        trustAllCerts[0] = tm;

        javax.net.ssl.SSLContext sc =

        javax.net.ssl.SSLContext.getInstance("SSL");

        sc.init(null, trustAllCerts, null);

        javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(

        sc.getSocketFactory());

    }

为什么它在 Java 中不起作用?

(出于安全原因,我更改了上面的网址。)

【问题讨论】:

  • 发布您在 Java 中尝试过的代码 sn-p 以及错误堆栈跟踪(如果有)。
  • @Ravinder 用代码更新了帖子
  • 任何错误堆栈?如果不是,你怎么能说“为什么它不能在 java 中工作?
  • 通过身份验证时不会出现任何错误,但数据未保存到服务器。当尝试获取它以 xml 格式获取的详细信息时,但是当我保存它时,它没有保存

标签: java curl


【解决方案1】:

所以您正尝试将do_not_disturb=no 发布到服务器?这就是为什么我在 cmets 中问你到你的previous question...

通过将?do_not_disturb=No 附加到 URL 中,这些参数会自动作为 GET 请求发送到服务器,要作为 POST 发送,您必须将它们放入请求正文中,如下所示:

String postData = "do_not_disturb=No";

OutputStreamWriter outputWriter = new OutputStreamWriter(uc.getOutputStream());
outputWriter.write(postData);
outputWriter.flush();
outputWriter.close();

那么你的Accept-Header 可能是错误的,因为它告诉服务器你期望以哪种格式获得一些响应数据(content)。如果您希望从服务器获取一些 XML,则应为 uc.setRequestProperty("Accept", "application/xml");

更新

通过将详细标志 (-v) 添加到您的 curl 命令,我得到了它正在发送的标头:

POST /api/domains/amj.nms.mixnetworks.net/subscribers/9001/ HTTP/1.1
Authorization: Basic {URL_ENCODED_AUTHENTICATION_STRING}
User-Agent: curl/7.22.0 (i686-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3
Host: 8.7.177.4
Accept: */*
Content-Length: 17
Content-Type: application/x-www-form-urlencoded

所以请尝试像这样更改您的代码:

uc.setRequestProperty("Authorization", String.format("Basic %s", encoding));
uc.setRequestMethod("POST");
uc.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
uc.setRequestProperty("Accept", "*/*");
uc.setRequestProperty("Content-Length", Integer.toString(postData.getBytes().length));

用户代理字符串应该是不感兴趣的,除非你的服务器正在做非常奇怪的事情。

如果它仍然不起作用,请查看您的变量 encoding 是否与详细 curl 运行中 Basic 之后的部分具有相同的值。

【讨论】:

  • 根据您的建议更改代码后,仍然没有保存
  • 请使用Wireshark并使用curl记录一个请求,并使用您的Java应用程序记录一个请求,然后与我们分享。
  • 您可以编辑您的问题,也可以将其上传到pastebin.com 或类似的服务。
  • 我用pcap的形式保存了记录的数据,但是pastebin支持吗?我是 WiresShark 的新手,请您提供更多详细信息
  • 不幸的是,我错过了您正在执行 HTTPS 请求,因此 Wireshark 在这里没有用。我将-v-flag(详细输出)添加到您的curl 命令中,并且可以获得该请求。我会尽快更新我的答案。
【解决方案2】:

在我的情况下,curl 适用于 POST 调用,java 中的 HttpUrlConnection 不起作用,返回 403 Forbidden 说我正在使用匿名登录,但是这个 POST 调用应该完成的实际工作已经完成。一开始非常混乱。然后发现我需要禁用url重定向(这是xtend代码但你明白了):

val conn = url.openConnection() as HttpURLConnection
conn.setInstanceFollowRedirects(false)

【讨论】:

    【解决方案3】:

    这里有几个选项。一种是您可以添加一个 Java 类来使用 Runtime().exec 运行 bash 脚本。

    但是,我调试了我的 Java 连接,发现我没有使用 TLSv1.2

            System.setProperty("deployment.security.TLSv1.2", "true");
            System.setProperty("https.protocols", "TLSv1.2");
            System.setProperty("javax.net.debug", "ssl"); // "" or "ssl"
    

    在我从 Java 7 迁移到 Java 8 之后,Java 命令起作用了。

    通常 curl 有效但 Java 无效,或者 Java 有效而 curl 无效。我通常检查 SSL 配置(使用 -v 和 -k 进行 curl),尝试更改 http 与 https 或在此处查看 SSL 证书安装程序:https://confluence.atlassian.com/download/attachments/180292346/InstallCert.java(我对此进行了修改以在运行时安装证书)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-22
      • 2018-04-10
      • 1970-01-01
      • 2019-02-11
      相关资源
      最近更新 更多