使用 httpclient 4.1.2 连接到 https 会给出 org.apache.http.client.ClientProtocolException

发布于 2024-12-15 02:00:50 字数 10118 浏览 1 评论 0原文

我已成功使用 此解决方案 < strong>android发布到接受所有证书的https服务器

现在我正在JAVA中尝试同样的事情发布到接受所有证书的https服务器。

我修改了上述网址中的 EasySSLSocketFactory 类,因为 SocketFactory、LayeredSocketFactory 类在 httpclient 4.1.2 版本中已弃用。上述 url 中的 EasyX509TrustManager 类保持不变。这是我修改过的 EasySSLSocketFactory。我已经标记了我修改过的类。

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;

import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.scheme.SchemeSocketFactory;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;


public class EasySSLSocketFactory implements SchemeSocketFactory
{
     private SSLContext sslcontext = null;

     private static SSLContext createEasySSLContext() throws IOException {
             try {
                     SSLContext context = SSLContext.getInstance("TLS");
                     context.init(null, new TrustManager[] { new EasyX509TrustManager(null) }, null);
                     return context;
             } catch (Exception e) {
                     throw new IOException(e.getMessage());
             }
     }


    private SSLContext getSSLContext() throws IOException {
             if (this.sslcontext == null) {
                     this.sslcontext = createEasySSLContext();
             }
             return this.sslcontext;
     }

     /**
      * @see org.apache.http.conn.scheme.SchemeSocketFactory#isSecure(java.net.Socket)
      */
     public boolean isSecure(Socket socket) throws IllegalArgumentException {
             return true;
     }

     // -------------------------------------------------------------------
     // javadoc in org.apache.http.conn.scheme.SocketFactory says :
     // Both Object.equals() and Object.hashCode() must be overridden
     // for the correct operation of some connection managers
     // -------------------------------------------------------------------

     public boolean equals(Object obj) {
             return ((obj != null) && obj.getClass().equals(
                             EasySSLSocketFactory.class));
     }

     public int hashCode() {
             return EasySSLSocketFactory.class.hashCode();
     }

    //this method is modified
    @Override
    public Socket connectSocket(Socket sock, InetSocketAddress remoteAddress,
            InetSocketAddress localAddress, HttpParams params) throws IOException,
            UnknownHostException, ConnectTimeoutException {

        int connTimeout = HttpConnectionParams.getConnectionTimeout(params);
        int soTimeout = HttpConnectionParams.getSoTimeout(params);
        SSLSocket sslsock = (SSLSocket) ((sock != null) ? sock : createSocket(params));
        if (localAddress != null) {
            // we need to bind explicitly
            sslsock.bind(localAddress);
    }

    sslsock.connect(remoteAddress, connTimeout);
    sslsock.setSoTimeout(soTimeout);
    return sslsock;
    }

    //this method is modified
    @Override
    public Socket createSocket(HttpParams arg0) throws IOException {
         return getSSLContext().getSocketFactory().createSocket();
    }

}

这是我的 httpclient。由于使用 httpclient 4.1.2,这个类也被修改了,

public class MyHttpClient extends DefaultHttpClient {

    /** The time it takes for our client to timeout */
    public static final int HTTP_TIMEOUT = 30 * 1000; // milliseconds
    public static final int SOCKET_TIMEOUT = 50 * 1000; // milliseconds


    public MyHttpClient() {
    }

    @Override
    protected ClientConnectionManager createClientConnectionManager() {

        SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
        // Register for port 443 our SSLSocketFactory to the ConnectionManager
        registry.register(new Scheme("https", 443, new EasySSLSocketFactory()));

        //setting the httpparams
        HttpParams params = new BasicHttpParams();
        //params.setParameter(ConnManagerPNames.MAX_TOTAL_CONNECTIONS, 1);
        //params.setParameter(ConnManagerPNames.MAX_CONNECTIONS_PER_ROUTE, new ConnPerRouteBean(1));
        params.setParameter(HttpProtocolParams.USE_EXPECT_CONTINUE, false);
        //HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
        HttpProtocolParams.setContentCharset(params, "utf8");

        return new SingleClientConnManager(registry);
    }

}

我尝试按以下方式连接

ArrayList<NameValuePair> postParameters = new ArrayList<NameValuePair>();
        postParameters.add(new BasicNameValuePair("userid", userid));
        postParameters.add(new BasicNameValuePair("password", password));
        String newresponse = null;
        BufferedReader in = null;
        try{
             DefaultHttpClient client = new MyHttpClient();
             try {        
                    HttpPost req = new HttpPost(my https url);
                    UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(postParameters);
                    req.setEntity(formEntity);
                    HttpResponse resp = client.execute(req);
                    in = new BufferedReader(new InputStreamReader(resp.getEntity().getContent()));
                    StringBuffer sb = new StringBuffer("");
                    String line = "";
                    String NL = System.getProperty("line.separator");
                    while ((line = in.readLine()) != null) {
                        sb.append(line + NL);
                    }
                    in.close();
                    newresponse = sb.toString();

                    }catch(Exception e){
                        LOGGER.error("Exception", e);
                    }finally {
                        if (in != null) {
                            try {
                                in.close();
                            } catch (IOException e) {
                                LOGGER.error("IOException: ",e);
                            }
                        }
                    }
        } catch(Exception e){
            LOGGER.debug("Connection Exception: ",e);
        }

当我尝试以上述方式连接到 https 服务器时,我得到

org.apache.http.client.ClientProtocolException
        at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:822)
        at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:754)
        at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:732)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:576)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
        at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:563)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:399)
        at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:317)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:204)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:182)
        at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:311)
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
        at java.lang.Thread.run(Thread.java:662)
Caused by: org.apache.http.HttpException: Unable to establish route: planned = HttpRoute[{}->https://mysiteurlhere]; current = HttpRoute[{s}->https://mysiteurlhere]
        at org.apache.http.impl.client.DefaultRequestDirector.establishRoute(DefaultRequestDirector.java:774)
        at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:577)
        at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:425)
        at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:820)
        ... 22 more

The server i am attempts to access is using来自 verisign 的证书,但我没有。所以我试图接受所有证书。将来我将更改此设置。

有人可以让它工作吗? 提前致谢。

I have successfully used this solution in android to post to https server accepting all certificates

Now i am trying the same thing in JAVA to post to https server accepting all certificates.

I modified the EasySSLSocketFactory class from the above url as SocketFactory, LayeredSocketFactory classes are deprecated in httpclient 4.1.2 version. EasyX509TrustManager class from the above url remains unchanged. Here is the EasySSLSocketFactory which i have modified.I have marked the classes which i have modified.

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;

import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.scheme.SchemeSocketFactory;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;


public class EasySSLSocketFactory implements SchemeSocketFactory
{
     private SSLContext sslcontext = null;

     private static SSLContext createEasySSLContext() throws IOException {
             try {
                     SSLContext context = SSLContext.getInstance("TLS");
                     context.init(null, new TrustManager[] { new EasyX509TrustManager(null) }, null);
                     return context;
             } catch (Exception e) {
                     throw new IOException(e.getMessage());
             }
     }


    private SSLContext getSSLContext() throws IOException {
             if (this.sslcontext == null) {
                     this.sslcontext = createEasySSLContext();
             }
             return this.sslcontext;
     }

     /**
      * @see org.apache.http.conn.scheme.SchemeSocketFactory#isSecure(java.net.Socket)
      */
     public boolean isSecure(Socket socket) throws IllegalArgumentException {
             return true;
     }

     // -------------------------------------------------------------------
     // javadoc in org.apache.http.conn.scheme.SocketFactory says :
     // Both Object.equals() and Object.hashCode() must be overridden
     // for the correct operation of some connection managers
     // -------------------------------------------------------------------

     public boolean equals(Object obj) {
             return ((obj != null) && obj.getClass().equals(
                             EasySSLSocketFactory.class));
     }

     public int hashCode() {
             return EasySSLSocketFactory.class.hashCode();
     }

    //this method is modified
    @Override
    public Socket connectSocket(Socket sock, InetSocketAddress remoteAddress,
            InetSocketAddress localAddress, HttpParams params) throws IOException,
            UnknownHostException, ConnectTimeoutException {

        int connTimeout = HttpConnectionParams.getConnectionTimeout(params);
        int soTimeout = HttpConnectionParams.getSoTimeout(params);
        SSLSocket sslsock = (SSLSocket) ((sock != null) ? sock : createSocket(params));
        if (localAddress != null) {
            // we need to bind explicitly
            sslsock.bind(localAddress);
    }

    sslsock.connect(remoteAddress, connTimeout);
    sslsock.setSoTimeout(soTimeout);
    return sslsock;
    }

    //this method is modified
    @Override
    public Socket createSocket(HttpParams arg0) throws IOException {
         return getSSLContext().getSocketFactory().createSocket();
    }

}

And here is my httpclient.This class is also modified because of using httpclient 4.1.2

public class MyHttpClient extends DefaultHttpClient {

    /** The time it takes for our client to timeout */
    public static final int HTTP_TIMEOUT = 30 * 1000; // milliseconds
    public static final int SOCKET_TIMEOUT = 50 * 1000; // milliseconds


    public MyHttpClient() {
    }

    @Override
    protected ClientConnectionManager createClientConnectionManager() {

        SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
        // Register for port 443 our SSLSocketFactory to the ConnectionManager
        registry.register(new Scheme("https", 443, new EasySSLSocketFactory()));

        //setting the httpparams
        HttpParams params = new BasicHttpParams();
        //params.setParameter(ConnManagerPNames.MAX_TOTAL_CONNECTIONS, 1);
        //params.setParameter(ConnManagerPNames.MAX_CONNECTIONS_PER_ROUTE, new ConnPerRouteBean(1));
        params.setParameter(HttpProtocolParams.USE_EXPECT_CONTINUE, false);
        //HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
        HttpProtocolParams.setContentCharset(params, "utf8");

        return new SingleClientConnManager(registry);
    }

}

I am trying to connect in the following way

ArrayList<NameValuePair> postParameters = new ArrayList<NameValuePair>();
        postParameters.add(new BasicNameValuePair("userid", userid));
        postParameters.add(new BasicNameValuePair("password", password));
        String newresponse = null;
        BufferedReader in = null;
        try{
             DefaultHttpClient client = new MyHttpClient();
             try {        
                    HttpPost req = new HttpPost(my https url);
                    UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(postParameters);
                    req.setEntity(formEntity);
                    HttpResponse resp = client.execute(req);
                    in = new BufferedReader(new InputStreamReader(resp.getEntity().getContent()));
                    StringBuffer sb = new StringBuffer("");
                    String line = "";
                    String NL = System.getProperty("line.separator");
                    while ((line = in.readLine()) != null) {
                        sb.append(line + NL);
                    }
                    in.close();
                    newresponse = sb.toString();

                    }catch(Exception e){
                        LOGGER.error("Exception", e);
                    }finally {
                        if (in != null) {
                            try {
                                in.close();
                            } catch (IOException e) {
                                LOGGER.error("IOException: ",e);
                            }
                        }
                    }
        } catch(Exception e){
            LOGGER.debug("Connection Exception: ",e);
        }

When i try to connect to https server in the above way i get

org.apache.http.client.ClientProtocolException
        at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:822)
        at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:754)
        at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:732)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:576)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
        at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:563)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:399)
        at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:317)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:204)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:182)
        at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:311)
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
        at java.lang.Thread.run(Thread.java:662)
Caused by: org.apache.http.HttpException: Unable to establish route: planned = HttpRoute[{}->https://mysiteurlhere]; current = HttpRoute[{s}->https://mysiteurlhere]
        at org.apache.http.impl.client.DefaultRequestDirector.establishRoute(DefaultRequestDirector.java:774)
        at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:577)
        at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:425)
        at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:820)
        ... 22 more

The server i am trying to access is using certificate from verisign which i don't have with me.So i am trying to accept all certificates.In the future i am going to change this.

Can anybody please make it work?
Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

相思故 2024-12-22 02:00:50

如果您希望 EasySSLSocketFactory 支持 SSL 隧道,则还必须实现 LayeredSchemeSocketFactory 接口。

Your EasySSLSocketFactory must also implement the LayeredSchemeSocketFactory interface if you want it to support SSL tunneling.

屌丝范 2024-12-22 02:00:50

您还需要为 SSLSockerFactory 注册Scheme:

httpClient.getConnectionManager().getSchemeRegistry().register(
    new Scheme("https", 443, SSLSocketFactory.getSystemSocketFactory())
);

Also you need to register Scheme for SSLSockerFactory:

httpClient.getConnectionManager().getSchemeRegistry().register(
    new Scheme("https", 443, SSLSocketFactory.getSystemSocketFactory())
);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文