如何解决android中的握手异常和认证异常

Posted

技术标签:

【中文标题】如何解决android中的握手异常和认证异常【英文标题】:How resolve Handshake Exception and Certification Exception in android 【发布时间】:2016-04-08 02:09:19 【问题描述】:

我想使用 https 访问 Web 服务,其证书将存储在服务器而不是应用程序上,我已经在我的信任管理器和 HostNameVerfier 中创建了一个密钥库,正如在堆栈溢出的许多问题中给出的那样,但我仍然得到访问 Web 服务时出现握手异常和证书异常。

我的证书扩展名是 .der。

这是我的代码

类 SendEncryptedData 扩展 AsyncTask ProgressDialog 对话框;

    @Override
    protected void onPreExecute() 
        super.onPreExecute();
        dialog = new ProgressDialog(LoginActivity.this);
        dialog.show();
    

    @Override
    protected String doInBackground(Object[] params) 
        TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        String DeviceId = telephonyManager.getDeviceId();

        try 


        HttpParams  client = new BasicHttpParams();
            final SchemeRegistry schemeRegistry = new SchemeRegistry();
            schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
            schemeRegistry.register(new Scheme("https", createAdditionalCertsSSLSocketFactory(), 443));


            HttpProtocolParams.setVersion(client, HttpVersion.HTTP_1_1);




            ThreadSafeClientConnManager singleClientConnManager = new ThreadSafeClientConnManager(client,schemeRegistry);
        DefaultHttpClient defaultHttpClient = new DefaultHttpClient(singleClientConnManager,client);


        HttpPost httpPost = new HttpPost(URL);


            JSONObject jsonObject = new JSONObject();
            jsonObject.accumulate("device",DeviceId);
            jsonObject.accumulate("login", encryptedEmail);
            jsonObject.accumulate("password", encryptedPassword);

            StringEntity stringEntity = new StringEntity(jsonObject.toString());

            httpPost.setEntity(stringEntity);
            HttpResponse httpResponse = defaultHttpClient.execute(httpPost);
            int statusCode=      httpResponse.getStatusLine().getStatusCode();
            String response =  httpResponse.getEntity().getContent().toString();

         catch (IOException e) 
            e.printStackTrace();
        catch (Exception ex)
        
            ex.printStackTrace();
        





    

    @Override
    protected void onPostExecute(Object o) 
        super.onPostExecute(o);
        dialog.dismiss();

        startActivity(new Intent(LoginActivity.this, MainActivity.class));
    







 protected org.apache.http.conn.ssl.SSLSocketFactory createAdditionalCertsSSLSocketFactory() 
        try 
            final KeyStore ks = KeyStore.getInstance("BKS");

            // the bks file we generated above
            final InputStream in = getResources().openRawResource( R.raw.analec);
            try 
                // don't forget to put the password used above in strings.xml/mystore_password
                ks.load(in, "password".toCharArray());
             finally 
                in.close();
            

            return new AdditionalKeyStoresSSLSocketFactory(ks);

         catch( Exception e ) 
            throw new RuntimeException(e);
        
    


public class AdditionalKeyStoresSSLSocketFactory extends SSLSocketFactory 
    protected SSLContext sslContext = SSLContext.getInstance("TLS");

    public AdditionalKeyStoresSSLSocketFactory(KeyStore keyStore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException 
        super(null, null, null, null, null, null);
        sslContext.init(null, new TrustManager[]new AdditionalKeyStoresTrustManager(keyStore), null);
    

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

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



    /**
     * Based on http://download.oracle.com/javase/1.5.0/docs/guide/security/jsse/JSSERefGuide.html#X509TrustManager
     */
    public static class AdditionalKeyStoresTrustManager implements X509TrustManager 

        protected ArrayList<X509TrustManager> x509TrustManagers = new ArrayList<X509TrustManager>();


        protected AdditionalKeyStoresTrustManager(KeyStore... additionalkeyStores) 
            final ArrayList<TrustManagerFactory> factories = new ArrayList<TrustManagerFactory>();

            try 
                // The default Trustmanager with default keystore
                final TrustManagerFactory original = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
                original.init((KeyStore) null);
                factories.add(original);

                for( KeyStore keyStore : additionalkeyStores ) 
                    final TrustManagerFactory additionalCerts = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
                    additionalCerts.init(keyStore);
                    factories.add(additionalCerts);
                

             catch (Exception e) 
                throw new RuntimeException(e);
            



            /*
             * Iterate over the returned trustmanagers, and hold on
             * to any that are X509TrustManagers
             */
            for (TrustManagerFactory tmf : factories)
                for( TrustManager tm : tmf.getTrustManagers() )
                    if (tm instanceof X509TrustManager)
                        x509TrustManagers.add( (X509TrustManager)tm );


            if( x509TrustManagers.size()==0 )
                throw new RuntimeException("Couldn't find any X509TrustManagers");

        

        /*
         * Delegate to the default trust manager.
         */
        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException 
            final X509TrustManager defaultX509TrustManager = x509TrustManagers.get(0);
            defaultX509TrustManager.checkClientTrusted(chain, authType);
        

        /*
         * Loop over the trustmanagers until we find one that accepts our server
         */
        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException 
            for( X509TrustManager tm : x509TrustManagers ) 
                try 
                    tm.checkServerTrusted(chain,authType);
                    return;
                 catch( CertificateException e ) 
                    // ignore
                
            
            throw new CertificateException();
        

        public X509Certificate[] getAcceptedIssuers() 
            final ArrayList<X509Certificate> list = new ArrayList<X509Certificate>();
            for( X509TrustManager tm : x509TrustManagers )
                list.addAll(Arrays.asList(tm.getAcceptedIssuers()));
            return list.toArray(new X509Certificate[list.size()]);
        
    


请告诉我如何解决这些问题。

【问题讨论】:

【参考方案1】:

这是一个临时解决方案,您可以在测试调试版本之前核对 ssl 证书,或者找到更好的解决方案

  public static class NukeSSLCerts 
    protected static final String TAG = "NukeSSLCerts";

    public static void nuke() 
        try 
            TrustManager[] trustAllCerts = new TrustManager[]
                    new X509TrustManager() 
                        public X509Certificate[] getAcceptedIssuers() 
                            X509Certificate[] myTrustedAnchors = new X509Certificate[0];
                            return myTrustedAnchors;
                        

                        @Override
                        public void checkClientTrusted(X509Certificate[] certs, String authType) 
                        

                        @Override
                        public void checkServerTrusted(X509Certificate[] certs, String authType) 
                        
                    
            ;

            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, trustAllCerts, new SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
            HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() 
                @Override
                public boolean verify(String arg0, SSLSession arg1) 
                    return true;
                
            );
         catch (Exception e) 
        
    

【讨论】:

查看这篇文章***.com/questions/15762249/… 我没有使用 Soap 服务。 这可以帮助你codeproject.com/Articles/826045/…

以上是关于如何解决android中的握手异常和认证异常的主要内容,如果未能解决你的问题,请参考以下文章

如何解决空指针异常和 ThreadException 中的错误android

如何解决空指针异常和 ThreadException 中的错误android

[Android]异常4-javax.mail.AuthenticationFailedException

如何修复 Android 模拟器中的“无法连接到相机服务”异常

在 android Nougat 中使用自签名证书通过 https 连接时出现 SSL 握手异常

在Android Nougat中使用自签名证书通过https连接时的SSL握手异常