发送GET HTTPS请求,但得到403禁止响应,为什么? [英] Send GET HTTPS request but get 403 forbidden response, why?

查看:854
本文介绍了发送GET HTTPS请求,但得到403禁止响应,为什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面是我送的WS握手完成后的网址

  \"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\"

它应该做的是重定向浏览器的网址给BackUrl页面。它在IE8尽管证书问题显示正确的结果。在Chrome浏览器的PC版本,它显示HTML的一些code。在Android中,我得到403 Forbidden错误。

  HTTP / 1.1 403禁止(服务器拒绝指定的统一资源定位器(URL)。与服务器管理员联系。)

我用这个方法将数据传送

  {尝试
            网址URL =新的URL(urlString);
            HttpsURLConnection.setDefaultHostnameVerifier(新FakeHostVerifier());            的TrustManager [] = trustAllCerts新的TrustManager [] {
                     新X509TrustManager(){
                         公共java.security.cert.X509Certificate [] getAcceptedIssuers()为{
                             Log.d(SSLDemo,getAcceptedIssuers);
                             返回null;
                         }
                         公共无效checkClientTrusted(
                             java.security.cert.X509Certificate []证书,字符串的authType){
                             Log.d(SSLDemo,检查客户端可信);
                         }
                         公共无效checkServerTrusted(
                             java.security.cert.X509Certificate []证书,字符串的authType){
                             Log.d(SSLDemo,检查服务器可信);
                         }
                     }
                 };
    的SSLContext SC = SSLContext.getInstance(TLS); //TLS
            sc.init(NULL,trustAllCerts,新java.security.SecureRandom中的());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
            INT端口= 443;
            SSLSocketFactory的工厂= HttpsURLConnection.getDefaultSSLSocketFactory();
            插座=(SSLSocket的)factory.createSocket(url.getHost(),端口);
            socket.startHandshake();
            / **
             *连接方法
             * /
            字符串的方法=GET;            串OS =方法++ urlString +HTTP / 1.0 \\ r \\ n;
            OS + =内容长度:0;
            OS + =\\ r \\ n \\ r \\ n;            ((SSLWeb)this.caller).updateRequest(urlString,法);            Log.i(TESTWEB,OS);
            BufferedWriter将WOUT =新的BufferedWriter(新OutputStreamWriter(socket.getOutputStream()));
            wout.write(OS);
            wout.flush();
            wout.close();
            RD =新的BufferedReader(新的InputStreamReader(socket.getInputStream()));            // *********不使用线程
            StringBuffer的BUFF =新的StringBuffer();            的char []缓冲区=新的char [1024];            而(rd.read(缓冲液)-1个){                buff.append(缓冲液);
                Log.i(TESTWEB,读缓冲器:+将String.valueOf(缓冲液));            }
            Log.i(TESTWEB,读行:+ buff.toString());            // **********        }赶上(例外五){
            Log.e(TESTWEB,连接错误,E);
            e.printStackTrace();
        }

是不是有什么毛病我code?我认为这个问题是与URL参数,但它在浏览器中运行:(

我一直在寻找一种方法解决此问题的最后三天了,至今没有运气。

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

 公共类FakeHostVerifier实现的HostnameVerifier {
    @覆盖
     公共布尔验证(字符串主机名,会议的SSLSession){
         返回true;
     }}


解决方案

正如我在另一个答案评论说,这无关与信任服务器的证书与否。如果收到的HTTP响应,即使它是一个403,这意味着在HTTP的连接被建立起来,这也意味着,底层SSL / TLS连接建立。如果你的客户不信任服务器证书,任何HTTP流量发生之前的SSL / TLS连接将关闭。

我想尝试的几件事情:


  • 删除的Content-Length 头。这是一个 GET 的要求,所以它没有一个实体。难不成一个长度为0的实体可能会混淆服务器。

  • 尝试设置用户代理头模拟请求来自浏览器的到来。

  • 更一般,看的头的工作将派遣并尝试重现他们的浏览器。 (尝试接受头为好,这可能是你的问题使用Chrome的原因。)

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

如果您 urlstring 变量真的包含了 HTTPS://ekp.truefriend.com/COVIWeb/gate / ... ,这就是问题的来源。

当你发送一个HTTP GET请求应该是这样的:

  GET / COVIWeb /门/ ... HTTP / 1.1
主持人:ekp.truefriend.com

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

(这是仅适用于通过代理请求,并不适用于HTTPS请求反正。)

如果你使用HTTP 1.0,你会不会使用主机头,但它不应该真正的问题(除非该主机提供多个虚拟主机,这它可以做,甚至通过HTTPS)。考虑使用HTTP / 1.1,如果可以的话,虽然你可能要处理关闭连接(内容长度或者分块编码)。

Below is the URL I send to the WS after the handshake is done

    "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"

What it should do is redirecting the browser to BackUrl page given in the url. It display correct result in IE8 despite the certificate problem. In PC version of Chrome it display some code of the HTML. In Android, I get 403 Forbidden error.

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

I use this method to stream data

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();
        }

Is there something wrong with my code? I thought the problem was with the URL parameter, but it work in browser :(

I've been finding a way around the problem for the last three days now, no luck so far.

EDIT: This is FakeHostVerifier class that used to skip the certificate validation process. Isn't this correct?

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

}

解决方案

As I was saying in a comment to another answer, this has nothing to do with trusting the server's certificate or not. If you get an HTTP response, even if it's a 403, that means that the HTTP connection was established, which also means that the underlying SSL/TLS connection was established. If your client doesn't trust the server certificate, the SSL/TLS connection will close before any HTTP traffic happens.

I'd try a few things:

  • Remove the Content-Length header. It's a GET request, so it doesn't have an entity. Implying a 0-length entity might confuse the server.
  • Try to set a User-Agent header to simulate the request as coming from a browser.
  • More generally, look at the headers a browser that work would send and try to reproduce them. (Try Accept header as well, that might be the cause of your problem with Chrome.)

EDIT: (other potential problem, more likely to be the cause)

If you urlstring variable really contains "https://ekp.truefriend.com/COVIWeb/gate/...", that's where the problem comes from.

When you send an HTTP GET the request should be like this:

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

Not:

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

(that's only for requests via a proxy, and doesn't apply to the HTTPS requests anyway.)

If you're using HTTP 1.0, you won't use the Host header, but it shouldn't really matter (unless that host serves multiple virtual hosts, which it can do, even over HTTPS). Consider using HTTP/1.1 if you can, although you may have to deal with closing the connection (content-length or chunked encoding perhaps).

这篇关于发送GET HTTPS请求,但得到403禁止响应,为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆