0

我一直在开发一个需要进行相互 ssl 身份验证的 rss 阅读器。我已经设法使用 Keychain API 获取用户证书,并且得到了似乎大部分工作的 SSLSocketFactory。但是每当我尝试与服务器建立连接时,我都会收到 401 Unauthorized 错误,我觉得这可能与我设置 SSL 连接和通用代码的方式有关。如果有人可以帮助指出我做错了什么以及我需要做什么,我将不胜感激。

主要活动:

public class AliasLoader extends AsyncTask<Void, Void, X509Certificate[]> 
{
    X509Certificate[] chain = null;

    @Override protected X509Certificate[] doInBackground(Void... params) {
        android.os.Debug.waitForDebugger();

        if(!SavedAlias.isEmpty())
        {
                try {
                    PrivateKey key2 = KeyChain.getPrivateKey(getApplicationContext(), SavedAlias);
                    setPrivateKey(key2);

                    chain = KeyChain.getCertificateChain(getApplicationContext(),SavedAlias);
                    setCertificate(chain);

                } catch (Exception e) {
                    Log.e(TAG, e.getMessage());
                }
        }
        else
        {
            this.cancel(true);
        }

        return chain;
    }

    @Override 
    protected void onPostExecute(X509Certificate[] chain) 
    {

        if(chain != null)
        {   
            HttpClient client = CustomSSLSocketFactory.getNewHttpClient(context, getAlias(), chain, key);
            String formDataServiceUrl = "https://android.diif.r.mil.uk";

            WebView wv = (WebView) findViewById(R.id.rssFeedItemView);

            HttpPost post = new HttpPost(formDataServiceUrl);
            final HttpGet request = new HttpGet(formDataServiceUrl);

            HttpResponse result = null;

            try {
                result = client.execute(post);
            } catch (ClientProtocolException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            wv.loadUrl(formDataServiceUrl);
        }
        else
        {
            Toast.makeText(getApplicationContext(), "Certificate is Empty", Toast.LENGTH_LONG).show();
        }
    }
}

自定义SSLSocketFactory:

    public class CustomSSLSocketFactory extends SSLSocketFactory {

public static KeyStore rootCAtrustStore = null;
public static KeyStore clientKeyStore = null;
SSLContext sslContext = SSLContext.getInstance("TLS");
Context context;

/**
 *  Constructor.
 */
 public CustomSSLSocketFactory(Context context, KeyStore keystore, String    keyStorePassword, KeyStore truststore)
        throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {

    super(keystore, keyStorePassword, truststore);
    this.context = context;

    // custom TrustManager,trusts all servers
    X509TrustManager tm = new X509TrustManager() {

        public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException {
        }

        public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException {
        }

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

Log.i("CLIENT CERTIFICATES", "Loaded client certificates: " + keystore.size());

// initialize key manager factory with the client certificate
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    keyManagerFactory.init(keystore,null);

sslContext.init(keyManagerFactory.getKeyManagers(), new TrustManager[] { tm }, 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();
}

/**
 *  Create new HttpClient with CustomSSLSocketFactory.
 */
public static HttpClient getNewHttpClient(Context context, String alias,  X509Certificate[] chain, PrivateKey key) {
    try {
        // This is method from tutorial ----------------------------------------------------
        //The root CA Trust Store
        rootCAtrustStore = KeyStore.getInstance("BKS");
        rootCAtrustStore.load(null);

        //InputStream in = context.getResources().openRawResource(com.DII.RSS_Viewer.R.raw.rootca);
        //rootCAtrustStore.load(in, "PASSWORD".toCharArray());

        //The Keystore with client certificates.
        //clientKeyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        clientKeyStore = KeyStore.getInstance("pkcs12");
        clientKeyStore.load(null);

        // client certificate is stored in android's keystore
        if((alias != null) && (chain != null))
        {
            Key pKey = key;
            clientKeyStore.setKeyEntry(alias, pKey, "password".toCharArray(), chain);
        }

        //SSLSocketFactory sf = new CustomSSLSocketFactory(context, clientKeyStore, "password", rootCAtrustStore);
        SSLSocketFactory sf = new SSLSocketFactory(clientKeyStore, "password");

        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", (SocketFactory) sf, 443));

        ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);

        return new DefaultHttpClient(ccm, params);
    } 
    catch (Exception e) 
    {
        return new DefaultHttpClient();
    }
    }
}
4

0 回答 0