发送GET HTTPS请求但得到403禁止响应,为什么?

时间:2010-09-16 09:35:53

标签: android ssl

以下是握​​手完成后发送给WS的URL

    "https://ekp.truefriend.com/COVIWeb/gate/AutoAuthentication.aspx?UserID=DP0001&BackUrl=http%3a%2f%2fgw.truefriendtest.com%2fCOVIWeb%2fApproval%2fForms%2fForm.aspx%3fmobileyn%3dY%26piid%3d96482621-6cc4-401c-a6f9-5ba6cb7ce26f%26wiid%3d425a9bc9-8607-4898-9158-ed9170da1d89%26fmpf%3dWF_A_DRAFT_PAPER01%26fmrv%3d0%26fiid%3d749526BE-B208-4987-B751-2DD0FC03F0F6%26fmid%3d24f6765d-69d1-429f-b0da-b540a064f0e2%26scid%3ddc4378f1-7edd-4d69-8fe4-5867ed32c8b9"

它应该做的是将浏览器重定向到url中给出的BackUrl页面。尽管存在证书问题,它仍在IE8中显示正确的结果。在PC版Chrome中,它会显示一些HTML代码。在Android中,我收到403 Forbidden错误。

HTTP/1.1 403 Forbidden ( The server denied the specified Uniform Resource Locator (URL). Contact the server administrator.  )

我使用此方法来传输数据

try{
            URL url = new URL(urlString);
            HttpsURLConnection.setDefaultHostnameVerifier(new FakeHostVerifier());

            TrustManager[] trustAllCerts = new TrustManager[]{
                     new X509TrustManager() {
                         public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                             Log.d("SSLDemo", "getAcceptedIssuers");
                             return null;
                         }
                         public void checkClientTrusted(
                             java.security.cert.X509Certificate[] certs, String authType) {
                             Log.d("SSLDemo", "Check Client Trusted");
                         }
                         public void checkServerTrusted(
                             java.security.cert.X509Certificate[] certs, String authType) {
                             Log.d("SSLDemo", "Check Server Trusted");
                         }
                     }
                 };


    SSLContext sc = SSLContext.getInstance("TLS"); //"TLS"
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
            int port = 443;
            SSLSocketFactory factory = HttpsURLConnection.getDefaultSSLSocketFactory();
            socket = (SSLSocket)factory.createSocket(url.getHost(), port);
            socket.startHandshake();


            /**
             * Connection Method
             */
            String method = "GET";

            String os = method + " "+urlString+" HTTP/1.0\r\n";
            os += "Content-Length: 0";
            os += "\r\n\r\n";

            ((SSLWeb)this.caller).updateRequest(urlString, method);

            Log.i("TESTWEB", os);
            BufferedWriter wout = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            wout.write(os);
            wout.flush();
            wout.close();
            rd = new BufferedReader(new InputStreamReader(socket.getInputStream()));

            //*********     Not using thread
            StringBuffer buff = new StringBuffer();

            char[] buffer = new char[1024];

            while(rd.read(buffer) > -1) {

                buff.append(buffer);
                Log.i("TESTWEB", "read buffer :" + String.valueOf(buffer));

            }
            Log.i("TESTWEB", "read line :" + buff.toString());

            //**********

        }catch(Exception e){
            Log.e("TESTWEB", "Connecting error", e);
            e.printStackTrace();
        }

我的代码有问题吗?我认为问题出在URL参数上,但它在浏览器中起作用:(

我过去三天一直在寻找解决问题的方法,到目前为止没有运气。

编辑:这是用于跳过证书验证过程的FakeHostVerifier类。这不正确吗?

 public class FakeHostVerifier implements HostnameVerifier {
    @Override
     public boolean verify(String hostname, SSLSession session) {
         return true;
     }

}

2 个答案:

答案 0 :(得分:5)

正如我在对另一个答案的评论中所说,这与信任服务器的证书无关。如果您收到HTTP响应,即使它是403,也表示已建立HTTP连接,这也意味着已建立基础SSL / TLS连接。如果您的客户端不信任服务器证书,则SSL / TLS连接将在任何HTTP流量发生之前关闭。

我会尝试一些事情:

  • 删除Content-Length标题。这是GET请求,因此它没有实体。暗示0长度的实体可能会混淆服务器。
  • 尝试设置User-Agent标头以模拟来自浏览器的请求。
  • 更一般地说,查看工作将发送并尝试重现它们的浏览器的标题。 (也可以尝试使用Accept标题,这可能是导致Chrome出现问题的原因。)

编辑:(其他潜在问题,更有可能是原因)

如果urlstring变量确实包含“https://ekp.truefriend.com/COVIWeb/gate/...”,那就是问题的来源。

当您发送HTTP GET时,请求应如下所示:

GET /COVIWeb/gate/... HTTP/1.1
Host: ekp.truefriend.com

GET https://ekp.truefriend.com/COVIWeb/gate/... HTTP/1.1

(仅适用于通过代理的请求,并且无论如何都不适用于HTTPS请求。)

如果您使用的是HTTP 1.0,则不会使用Host标头,但它并不重要(除非该主机为多个虚拟主机提供服务,即使通过HTTPS也可以这样做)。如果可以,请考虑使用HTTP / 1.1,尽管您可能必须处理关闭连接(可能是内容长度或分块编码)。

答案 1 :(得分:2)

您的问题包含答案。在尝试访问您在Chrome中指定的网址时,会收到一条红色警告“该网站的安全证书不受信任!”。虽然您可以在浏览器中手动覆盖并忽略警告,但您的代码会将此视为安全问题和死胡同。它甚至建议您联系服务器管理员。

如果您是服务器的管理员,请将SSL证书更改为有效证书。如果没有,请管理员这样做。如果不这样做,请尝试访问网站的HTTP(非SSL)版本。