简体   繁体   English

Android如何允许来自特定服务器的特定SSL证书

[英]Android How to allow specific SSL certificate from a specific server

I'm trying to connect to my secured server using HTTPS using DefaultHttpClient. 我正在尝试使用DefaultHttpClient使用HTTPS连接到我的安全服务器。

My server is using PositiveSSL certificate and every check i've made through the SSL checkers online - gives an A grade for the certificate. 我的服务器使用的是PositiveSSL证书,我通过SSL检查器在线进行的每项检查都为该证书提供A级。

Apperantly, PositiveSSL is not a verified CA Root in Android so when i'm ever i'm trying to connect to my server I'm receiving the javax.net.ssl.SSLPeerUnverifiedException: No peer certificate which is discussed here in various questions. 显然,PositiveSSL不是Android中经过验证的CA Root,因此,当我尝试连接到服务器时,会收到javax.net.ssl.SSLPeerUnverifiedException: No peer certificate在这里讨论各种问题的javax.net.ssl.SSLPeerUnverifiedException: No peer certificate

One of the given solution (that was the best for me) is to create a custom SSLFactory and to allow it to accept the unverified certificate, in case this certificate is coming from my server (to set the allowed server's name). 给定的解决方案之一(最适合我的方法)是创建一个自定义SSLFactory,并允许它接受未验证的证书,以防该证书来自我的服务器(设置允许的服务器名称)。

I couldn't find any code examples on how to do it.. would be great if someone will be kind to help me with that 我找不到任何有关如何执行此操作的代码示例。如果有人愿意帮助我,那将非常好

Yopu can Write you Custom SSLSocketFactory as given below Yopu可以按如下所示为您编写自定义SSLSocketFactory

 public class MySSLSocketFactory extends SSLSocketFactory {
 SSLContext sslContext = SSLContext.getInstance("TLS");

 public MySSLSocketFactory(KeyStore truststore)
        throws NoSuchAlgorithmException, KeyManagementException,
        KeyStoreException, UnrecoverableKeyException {
    super(truststore);

    TrustManager tm = new X509TrustManager() {
        @Override
        public void checkClientTrusted(X509Certificate[] chain,
                                       String authType) throws CertificateException {
        }

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

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

    sslContext.init(null, new TrustManager[]{tm}, null);
}

@Override
public Socket createSocket(Socket socket, String host, int port,
                           boolean autoClose) throws IOException, UnknownHostException {
    return sslContext.getSocketFactory().createSocket(socket, host, port,
            autoClose);
}

@Override
public Socket createSocket() throws IOException {
    return sslContext.getSocketFactory().createSocket();
}
 }

Now Create a Custom HttpClient using the SocketFactory to by Pass the certificate. 现在,使用SocketFactory创建自定义HttpClient,以通过证书。 You can also accept some particular Certificate as well using your SockeFactory. 您也可以使用SockeFactory接受某些特定的证书。

   public static DefaultHttpClient getNewHttpClient() {
    try {
        KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
        trustStore.load(null, null);
        SSLSocketFactory sf = new MySSLSocketFactory(trustStore);
        sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        HttpParams params = new BasicHttpParams();
        HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
        HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
        SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
        registry.register(new Scheme("https", sf, 443));

        ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);

        return new DefaultHttpClient(ccm, params);

    } catch (UnrecoverableKeyException e) {
        return new DefaultHttpClient();
    } catch (NoSuchAlgorithmException e) {
        return new DefaultHttpClient();
    } catch (CertificateException e) {
        return new DefaultHttpClient();
    } catch (IOException e) {
        return new DefaultHttpClient();
    } catch (KeyStoreException e) {
        return new DefaultHttpClient();
    } catch (KeyManagementException e) {
        return new DefaultHttpClient();
    }
}

Now Use instantiate httpclient as mentioned : 现在使用提到的实例化httpclient:

DefaultHttpClient client = getNewHttpClient();

Check emmby Answer on this post 检查此帖子的emmby答案

Trusting all certificates using HttpClient over HTTPS 通过HTTPS使用HttpClient信任所有证书

UPDATED : 更新 :

If you want to verify only some particular server. 如果您只想验证某些特定服务器。 Open the url in browser with Https and download the certificate from the url bar , Its easy Google it how to do that. 在浏览器中使用Https打开url,然后从url栏中下载证书,这很简单,Google如何操作。 It will give you a certificate file. 它会给您一个证书文件。

Copy that certificate in your assest folder. 将该证书复制到您的资产文件夹中。 and do the following. 并执行以下操作。

  private X509Certificate getCertFromFile(String path) throws Exception {
     AssetManager assetManager = MyActivity.this.getResources().getAssets();
     InputStream inputStream = null;
     try {
         inputStream = assetManager.open(path);
     } catch (IOException e) {
         e.printStackTrace();
     }
     InputStream caInput = new BufferedInputStream(inputStream);
     X509Certificate cert = null;
     CertificateFactory cf = CertificateFactory.getInstance("X509");
     cert = (X509Certificate) cf.generateCertificate(caInput);
     cert.getSerialNumber();
     return cert;
  }

Now in above code for socket Factory return this certificate instead of null. 现在,在上面用于套接字工厂的代码中,返回此证书而不是null。

 @Override
    public X509Certificate[] getAcceptedIssuers() {
        X509Certificate[] certificates=new X509Certificate[]{getCertFromFile(PATH_OF_CERTIFICATE_FILE)};

       return certificates;
         //asset folder path is  taken in method.Only provide path respective to asset folder like /certificate/MyCertificate.crt inside assest.

    }

You can place the custom server certificate in a custom trust store (BKS file), include it in your app and initialize your SSLSocketFactory with it: 您可以将自定义服务器证书放在自定义信任存储区(BKS文件)中,将其包含在应用程序中,并使用它初始化SSLSocketFactory:

SSLSocketFactory sslSocketFactory = new SSLSocketFactory(trustStore);

Afterwards use that SSLSocketFactory for creating your connections. 然后,使用该SSLSocketFactory创建连接。

In such a case only connections to servers which certificate is included in the key store. 在这种情况下,仅连接到密钥库中包含证书的服务器。

A very good example how this can be used with HttpClient can be found on Nikolay Elenkov's home page (section Using your own trust store: HttpClient ): 可以在Nikolay Elenkov的主页上找到一个很好的示例,该示例可以与HttpClient一起使用( 使用您自己的信任存储区:HttpClient一节 ):

http://nelenkov.blogspot.de/2011/12/using-custom-certificate-trust-store-on.html http://nelenkov.blogspot.de/2011/12/using-custom-certificate-trust-store-on.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 TrustManager仅允许一个特定的不受信任的证书 - Allow only one specific untrusted certificate by the TrustManager 在 Tomcat 服务器上从 Ionos 安装 SSL 证书,“未找到 Android SSL 连接的信任锚点” - Installing SSL certificate from Ionos on Tomcat server, "Trust Anchor not found for Android SSL Connection" 如何从android 10中特定位置的服务器下载任何文件? - How to download any file from server on specific location in android 10? 仅允许通过特定的移动应用访问服务器上的文件 - Allow accessing files on server from a specific mobile app only 如何从 SSL 证书中提取附加信息以允许访问 WAS 上的 WebService 客户端 - How to extracts additional info from SSL certificate to allow access to WebService client on WAS 如何通过 Windows 命令提示符使用 Java Keytool 指定现有 SSL 证书的文件路径? - How do I specific a file path to an existing SSL certificate using Java Keytool via Windows Command Prompt? SSL - 仅允许特定客户端或服务器(Java信任库) - SSL - only allow specific clients or servers (Java truststore) 如何在Android中使用自签名SSL证书 - How to use a self signed SSL certificate in Android 如何允许词法分析器解析 java 中的特定代码部分? - How to allow lexer to parse specific code parts from java? 使用Android WebViewClient启用特定的SSL协议 - Enabling specific SSL protocols with Android WebViewClient
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM