Android 上的 httpclient ssl 证书

发布于 2024-09-02 02:32:33 字数 1223 浏览 6 评论 0原文

我在 Android 上使用 httpclient 时遇到一些 ssl 问题,我正在尝试详细访问自签名证书,我希望我的应用程序信任所有证书(我将仅使用 ssl 进行数据加密)。首先我尝试使用本指南 http://hc.apache.org/httpclient- 3.x/sslguide.html 在桌面上工作正常,但在 Android 上我仍然得到 javax.net.ssl.SSLException: 不受信任的服务器证书。在谷歌搜索后,我发现了一些其他示例如何启用 ssl。

http://groups.google.com/group/android-developers/ browser_thread/thread/62d856cdcfa9f16e - 当我使用 URLConnection 但使用 HttpClient 时仍然出现异常。

http://www.discursive.com/ books/cjcook/reference/http-webdav-sect-self-signed.html - 在桌面上使用 apache 的 jar 可以正常工作,但在 android 中使用 SDK 类中包含的文件无法使其工作。

http:// /mail-archives.apache.org/mod_mbox/hc-httpclient-users/200808.mbox/%3C1218824624.6561.14.camel@ubuntu%3E - 也得到相同的异常

所以有什么想法我如何信任所有证书在 Android 上使用 HttpClient

I have some troubles with ssl using httpclient on android i am trying to access self signed certificate in details i want my app to trust all certificates ( i will use ssl only for data encryption). First i tried using this guide http://hc.apache.org/httpclient-3.x/sslguide.html on Desktop is working fine but on android i still got javax.net.ssl.SSLException: Not trusted server certificate. After searching in google i found some other examples how to enable ssl.

http://groups.google.com/group/android-developers/browse_thread/thread/62d856cdcfa9f16e - Working when i use URLConnection but with HttpClient still got the exception.

http://www.discursive.com/books/cjcook/reference/http-webdav-sect-self-signed.html - on Desktop using jars from apache is working but in android using included in SDK classes can't make it work.

http://mail-archives.apache.org/mod_mbox/hc-httpclient-users/200808.mbox/%3C1218824624.6561.14.camel@ubuntu%3E - also get the same exception

So any ideas how can i trust all certificates on android using HttpClient

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

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

发布评论

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

评论(3

慢慢从新开始 2024-09-09 02:32:33

如果您碰巧查看了 DefaultHttpClient 的代码,它看起来像这样:

   @Override
    protected ClientConnectionManager createClientConnectionManager() {
        SchemeRegistry registry = new SchemeRegistry();
        registry.register(
                new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
        registry.register(
                new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));

        ClientConnectionManager connManager = null;     
        HttpParams params = getParams();
        ...
    }

注意 https 方案到 org.apache.http.conn.ssl.SSLSocketFactory.getSocketFactory() 的映射。

您可以为 org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory 接口创建自定义实现 (http://hc.apache.org/httpclient-3.x/apidocs/org/apache/commons/httpclient/protocol/SecureProtocolSocketFactory。 html),其中,您可以使用接受所有证书的自定义 TrustManager 创建 java.net.SSLSocket

您可能需要在 中查看 JSSE 以了解更多详细信息http://java.sun.com/j2se/1.4.2/docs/guide/security/jsse/JSSERefGuide.html

If you happen to look at the code of DefaultHttpClient, it looks something like this:

   @Override
    protected ClientConnectionManager createClientConnectionManager() {
        SchemeRegistry registry = new SchemeRegistry();
        registry.register(
                new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
        registry.register(
                new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));

        ClientConnectionManager connManager = null;     
        HttpParams params = getParams();
        ...
    }

Notice the mapping of https scheme to org.apache.http.conn.ssl.SSLSocketFactory.getSocketFactory().

You can create a custom implementation for org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory interface (http://hc.apache.org/httpclient-3.x/apidocs/org/apache/commons/httpclient/protocol/SecureProtocolSocketFactory.html) wherein, you can create java.net.SSLSocket with a custom TrustManager that accepts all certificate.

You may want to look into JSSE for more details at http://java.sun.com/j2se/1.4.2/docs/guide/security/jsse/JSSERefGuide.html

日裸衫吸 2024-09-09 02:32:33

关键思想是使用自定义的 SSLSocketFactory 实现 LayeredSocketFactory。定制的socket不需要HostNameVerifier。

private static final class TrustAllSSLSocketFactory implements
    LayeredSocketFactory {

    private static final TrustAllSSLSocketFactory DEFAULT_FACTORY = new TrustAllSSLSocketFactory();

    public static TrustAllSSLSocketFactory getSocketFactory() {
        return DEFAULT_FACTORY;
    }

    private SSLContext sslcontext;
    private javax.net.ssl.SSLSocketFactory socketfactory;

    private TrustAllSSLSocketFactory() {
        super();
        TrustManager[] tm = new TrustManager[] { new X509TrustManager() {

            @Override
            public void checkClientTrusted(X509Certificate[] chain,
                String authType) throws CertificateException {
                // do nothing
            }

            @Override
            public void checkServerTrusted(X509Certificate[] chain,
                String authType) throws CertificateException {
                // do nothing
            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }

        } };
        try {
            this.sslcontext = SSLContext.getInstance(SSLSocketFactory.TLS);
            this.sslcontext.init(null, tm, new SecureRandom());
            this.socketfactory = this.sslcontext.getSocketFactory();
        } catch ( NoSuchAlgorithmException e ) {
            Log.e(LOG_TAG,
                "Failed to instantiate TrustAllSSLSocketFactory!", e);
        } catch ( KeyManagementException e ) {
            Log.e(LOG_TAG,
                "Failed to instantiate TrustAllSSLSocketFactory!", e);
        }
    }

    @Override
    public Socket createSocket(Socket socket, String host, int port,
        boolean autoClose) throws IOException, UnknownHostException {
        SSLSocket sslSocket = (SSLSocket) this.socketfactory.createSocket(
            socket, host, port, autoClose);
        return sslSocket;
    }

    @Override
    public Socket connectSocket(Socket sock, String host, int port,
        InetAddress localAddress, int localPort, HttpParams params)
        throws IOException, UnknownHostException, ConnectTimeoutException {
        if ( host == null ) {
            throw new IllegalArgumentException(
                "Target host may not be null.");
        }
        if ( params == null ) {
            throw new IllegalArgumentException(
                "Parameters may not be null.");
        }

        SSLSocket sslsock = (SSLSocket) ( ( sock != null ) ? sock
            : createSocket() );

        if ( ( localAddress != null ) || ( localPort > 0 ) ) {

            // we need to bind explicitly
            if ( localPort < 0 ) {
                localPort = 0; // indicates "any"
            }

            InetSocketAddress isa = new InetSocketAddress(localAddress,
                localPort);
            sslsock.bind(isa);
        }

        int connTimeout = HttpConnectionParams.getConnectionTimeout(params);
        int soTimeout = HttpConnectionParams.getSoTimeout(params);

        InetSocketAddress remoteAddress;
        remoteAddress = new InetSocketAddress(host, port);

        sslsock.connect(remoteAddress, connTimeout);

        sslsock.setSoTimeout(soTimeout);

        return sslsock;
    }

    @Override
    public Socket createSocket() throws IOException {
        // the cast makes sure that the factory is working as expected
        return (SSLSocket) this.socketfactory.createSocket();
    }

    @Override
    public boolean isSecure(Socket sock) throws IllegalArgumentException {
        return true;
    }

}

然后,您可以继续在支持的方案注册表中使用自定义的 SSLSocketFactory。

private static final BasicHttpParams sHttpParams = new BasicHttpParams();
private static final SchemeRegistry sSupportedSchemes = new SchemeRegistry();
static {
    sHttpParams.setParameter("http.socket.timeout", READ_TIMEOUT);
    sHttpParams.setParameter("http.connection.timeout", CONNECT_TIMEOUT);
    sSupportedSchemes.register(new Scheme("http",
        PlainSocketFactory.getSocketFactory(), 80));
    sSupportedSchemes.register(new Scheme("https",
        TrustAllSSLSocketFactory.getSocketFactory(), 443));
}

The key idea is to use a customized SSLSocketFactory implementing LayeredSocketFactory. The customized socket doesn't need to HostNameVerifier.

private static final class TrustAllSSLSocketFactory implements
    LayeredSocketFactory {

    private static final TrustAllSSLSocketFactory DEFAULT_FACTORY = new TrustAllSSLSocketFactory();

    public static TrustAllSSLSocketFactory getSocketFactory() {
        return DEFAULT_FACTORY;
    }

    private SSLContext sslcontext;
    private javax.net.ssl.SSLSocketFactory socketfactory;

    private TrustAllSSLSocketFactory() {
        super();
        TrustManager[] tm = new TrustManager[] { new X509TrustManager() {

            @Override
            public void checkClientTrusted(X509Certificate[] chain,
                String authType) throws CertificateException {
                // do nothing
            }

            @Override
            public void checkServerTrusted(X509Certificate[] chain,
                String authType) throws CertificateException {
                // do nothing
            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }

        } };
        try {
            this.sslcontext = SSLContext.getInstance(SSLSocketFactory.TLS);
            this.sslcontext.init(null, tm, new SecureRandom());
            this.socketfactory = this.sslcontext.getSocketFactory();
        } catch ( NoSuchAlgorithmException e ) {
            Log.e(LOG_TAG,
                "Failed to instantiate TrustAllSSLSocketFactory!", e);
        } catch ( KeyManagementException e ) {
            Log.e(LOG_TAG,
                "Failed to instantiate TrustAllSSLSocketFactory!", e);
        }
    }

    @Override
    public Socket createSocket(Socket socket, String host, int port,
        boolean autoClose) throws IOException, UnknownHostException {
        SSLSocket sslSocket = (SSLSocket) this.socketfactory.createSocket(
            socket, host, port, autoClose);
        return sslSocket;
    }

    @Override
    public Socket connectSocket(Socket sock, String host, int port,
        InetAddress localAddress, int localPort, HttpParams params)
        throws IOException, UnknownHostException, ConnectTimeoutException {
        if ( host == null ) {
            throw new IllegalArgumentException(
                "Target host may not be null.");
        }
        if ( params == null ) {
            throw new IllegalArgumentException(
                "Parameters may not be null.");
        }

        SSLSocket sslsock = (SSLSocket) ( ( sock != null ) ? sock
            : createSocket() );

        if ( ( localAddress != null ) || ( localPort > 0 ) ) {

            // we need to bind explicitly
            if ( localPort < 0 ) {
                localPort = 0; // indicates "any"
            }

            InetSocketAddress isa = new InetSocketAddress(localAddress,
                localPort);
            sslsock.bind(isa);
        }

        int connTimeout = HttpConnectionParams.getConnectionTimeout(params);
        int soTimeout = HttpConnectionParams.getSoTimeout(params);

        InetSocketAddress remoteAddress;
        remoteAddress = new InetSocketAddress(host, port);

        sslsock.connect(remoteAddress, connTimeout);

        sslsock.setSoTimeout(soTimeout);

        return sslsock;
    }

    @Override
    public Socket createSocket() throws IOException {
        // the cast makes sure that the factory is working as expected
        return (SSLSocket) this.socketfactory.createSocket();
    }

    @Override
    public boolean isSecure(Socket sock) throws IllegalArgumentException {
        return true;
    }

}

You can then continue to use the customized SSLSocketFactory in the supported scheme registry.

private static final BasicHttpParams sHttpParams = new BasicHttpParams();
private static final SchemeRegistry sSupportedSchemes = new SchemeRegistry();
static {
    sHttpParams.setParameter("http.socket.timeout", READ_TIMEOUT);
    sHttpParams.setParameter("http.connection.timeout", CONNECT_TIMEOUT);
    sSupportedSchemes.register(new Scheme("http",
        PlainSocketFactory.getSocketFactory(), 80));
    sSupportedSchemes.register(new Scheme("https",
        TrustAllSSLSocketFactory.getSocketFactory(), 443));
}
初与友歌 2024-09-09 02:32:33

我建议使用以下解决方案,而不是接受所有证书: 信任所有证书通过 HTTPS 使用 HttpClient

Rather than accepting all certificates, I recommend this solution: Trusting all certificates using HttpClient over HTTPS

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