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

Rob*_*hai 1 ssl android

下面是握手完成后发送给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"
Run Code Online (Sandbox Code Playgroud)

它应该做的是将浏览器重定向到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.  )
Run Code Online (Sandbox Code Playgroud)

我使用这种方法来传输数据

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();
        }
Run Code Online (Sandbox Code Playgroud)

我的代码有问题吗?我认为问题是与URL参数,但它在浏览器中工作:(

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

编辑:这是FakeHostVerifier类,用于跳过证书验证过程.这不对吗?

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

}
Run Code Online (Sandbox Code Playgroud)

Bru*_*uno 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
Run Code Online (Sandbox Code Playgroud)

不:

GET https://ekp.truefriend.com/COVIWeb/gate/... HTTP/1.1
Run Code Online (Sandbox Code Playgroud)

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

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

  • 非常感谢.这个惊人的细节确实有帮助 (2认同)