【问题标题】:POST over SSL/HTTPS REST Api Android is responding 400 Bad RequestPOST over SSL/HTTPS REST Api Android 响应 400 Bad Request
【发布时间】:2011-07-12 13:15:13
【问题描述】:

在我的应用程序中,我想将我的 android 应用程序 XML 数据发布到使用 REST 服务的远程服务器中。我的代码如下:

 String url = "api.example.com";
    int port = 443;
    String query = "<?xml version='1.0' encoding='UTF-8'?><request><client><name>APIappDevAccount</name><password>123456</password></client><user><name>foyzulkarim</name><password>123456</password><groupId>12345</groupId></user></request>";
    Socket socket = null;
    try {
    socket =  new Socket(url,port);
    } catch (UnknownHostException e2) {
                // TODO Auto-generated catch block
                e2.printStackTrace();
            } catch (IOException e2) {
                // TODO Auto-generated catch block
                e2.printStackTrace();
            }
    BufferedReader br = null;
            try {
                br = new BufferedReader(new InputStreamReader(socket.getInputStream()));                        
            } catch (IOException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
            PrintStream pw = null;
            try {
                pw = new PrintStream(socket.getOutputStream());

            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            pw.print("POST api.example.com/rest/rest/user");
    pw.print("Content-Type: application/xml");
            pw.print("Content-Length:" + query.length());
            pw.print(query);
            System.out.println("hello foysal.");
            //get result
            String l = null;
            String text="";

            try {
                while ((l=br.readLine())!=null) {
                    System.out.println(l);
            text+=l;        
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            pw.close();
            try {
                br.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

但是该服务器在 SSL/HTTPS 协议之后,所以我收到以下 400 Bad Request 作为响应。

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"><html><head><title>400 Bad Request</title></head><body><h1>Bad Request</h1><p>Your browser sent a request that this server could not understand.<br />Reason: You're speaking plain HTTP to an SSL-enabled server port.<br />Instead use the HTTPS scheme to access this URL, please.<br /><blockquote>Hint: <a href="https://api.example.com/"><b>https://api.example.com/</b></a></blockquote></p></body></html>

如果我像下面这样使用 SSLSocketFactory

SocketFactory socketFactory = SSLSocketFactory.getDefault();
    Socket socket = null;

    try {
        socket = socketFactory.createSocket(url, port);

我遇到了异常

javax.net.ssl.SSLException: Not trusted server certificate
java.security.cert.CertPathValidatorException: TrustAnchor for CertPath not found.

一行

br = new BufferedReader(new InputStreamReader(socket.getInputStream()));

我的问题是,在上述场景中,如何通过 SSL 从 android 应用程序发布数据? 我想我们很多人都面临这个问题,所以我请求你给我/我们一些详细的答案。干杯。

【问题讨论】:

    标签: sockets post ssl restful-authentication


    【解决方案1】:

    太多未知数:-)

    在您可以控制的测试服务器上尝试纯 HTTP。 我的预感是它会给出同样的错误。 例如,您似乎没有在 HTTP 标头和正文之间放置一个空行。

    你为什么要重新实现 HTTP?不要告诉我没有可以在任何平台上使用的 API 或库?通常有 java.net.HttpUrlConnection 或 Apache HttpClient。

    编辑:

    嘿,看看 google 带来了什么:http://developer.android.com/reference/android/net/http/AndroidHttpClient.html

    【讨论】:

    • 如果我使用 HttpClient,我找不到删除或更新命令的任何示例。更重要的是,发布 xml 是 api 的主要要求。
    • 服务是否通过纯 HTTP 接受您的请求? 400 bad request 表明 SSL 工作正常,但您手工制作的 HTTP 格式错误。 PrintStream.print 是否甚至用换行符终止每个标题?我仍然建议使用 Apache HttpClient,因为它似乎已经在您的平台上可用,而不会增加应用程序的占用空间。它支持的方法比我知道的要多:hc.apache.org/httpclient-3.x/methods.html
    • 我想要的在线程stackoverflow.com/questions/6571480/…中详细说明
    • 如您所见,我想发布 XML。那里提到的问题已经解决,但我现在想要 SSL 相关的解决方案。这就是我在这里问的原因。感谢您的帮助。
    【解决方案2】:

    看来我需要添加 TrustAnchor 证书 才能验证整个钥匙链。 我已经向我的 API 提供者请求了这个证书,他们给了我可以从中获取证书的 Web 链接。 [为保密起见,我更改了网页链接]

    https://www.example.com/library/......SSL_bundle.pem

    他们还告诉我尝试连接(我猜应该从命令提示符执行)

    openssl s_client -connect api.example.com:443 -CAfile /root/SSL_bundle.pem
    

    然后我必须将证书集成到我的应用程序中。

    我现在将尝试了解如何集成该证书,但该讨论应该在另一个问题中进行。

    【讨论】:

      【解决方案3】:

      我已经做到了。代码如下。

      private String executeRequest(String targetURL, final String requestMethod,
                  String soap_request_message_header, String soap_request_message_body) {
              URL url;
              HttpURLConnection connection = null;
              try {
                  url = new URL(targetURL);
                  connection = (HttpURLConnection) url.openConnection();
                  connection.setRequestMethod(requestMethod);
      
                  connection.setRequestProperty("SOAPAction",
                          soap_request_message_header);
      
                  connection.setUseCaches(false);
                  connection.setDoInput(true);
                  connection.setDoOutput(true);
      
                  // Send request
                  DataOutputStream wr = new DataOutputStream(connection
                          .getOutputStream());
                  wr.writeBytes(soap_request_message_body);
                  wr.flush();
                  wr.close();
      
                  // Get Response
                  InputStream is;
                  final int responseCode = connection.getResponseCode();
                  Log.i("response", "code=" + responseCode);
                  if (responseCode <= 400) {
                      is = connection.getInputStream();
                  } else {
                      /* error from server */
                      is = connection.getErrorStream();
                  }
                  // is= connection.getInputStream();
                  BufferedReader rd = new BufferedReader(new InputStreamReader(is));
                  String line;
                  StringBuffer response = new StringBuffer();
                  while ((line = rd.readLine()) != null) {
                      response.append(line);
                      response.append('\r');
                  }
                  rd.close();
                  Log.i("response", "" + response.toString());
                  return response.toString();
      
              } catch (Exception e) {
      
                  Log.e("error https", "", e);
                  return e.getMessage();
      
              } finally {
      
                  if (connection != null) {
                      connection.disconnect();
                  }
              }
          }
      

      【讨论】:

        猜你喜欢
        • 2012-04-25
        • 1970-01-01
        • 2015-06-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多