java – 自动或用户选择适当的客户端证书的请求
|
我正在开发一个可能连接到不同服务器的混合cordova应用程序.其中一些确实需要客户证书. 在Android手机上安装相应的根证书客户端证书. 在Chrome浏览器上,我得到以下对话框,为Web连接选择相应的客户端证书. 使用cordova插件cordova-client-cert-authentication,在WebView中弹出相同的Http(s)请求对话框. 我的问题是如何在原生Android平台上实现Http(s)请求的自动证书选择,而无需明确声明相应的客户端证书.或者在Chrome上实现的用户选择证书是否类似? 这是当前的实现,它会抛出握手异常: try {
URL url = new URL( versionUrl );
HttpsURLConnection urlConnection = ( HttpsURLConnection ) url.openConnection();
urlConnection.setConnectTimeout( 10000 );
InputStream in = urlConnection.getInputStream();
}
catch(Exception e)
{
//javax.net.ssl.SSLHandshakeException: Handshake failed
}
解决方法您可以使用先前安装在Android KeyChain(系统密钥库)中的证书,扩展X509ExtendedKeyManager以配置URLConnection使用的SSLContext证书由您需要的别名引用.要使用类似于chrome的对话框提示用户进行选择: KeyChain.choosePrivateKeyAlias(this,this,// Callback
new String[] {"RSA","DSA"},// Any key types.
null,// Any issuers.
null,// Any host
-1,// Any port
DEFAULT_ALIAS);
这是使用自定义KeyManager配置SSL连接的代码.它使用默认的TrustManager和HostnameVerifier.如果服务器使用Android默认信任库中不存在的自签名证书,则需要配置它们(不建议信任所有证书) //Configure trustManager if needed
TrustManager[] trustManagers = null;
//Configure keyManager to select the private key and the certificate chain from KeyChain
KeyManager keyManager = KeyChainKeyManager.fromAlias(
context,mClientCertAlias);
//Configure SSLContext
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(new KeyManager[] {keyManager},trustManagers,null);
//Perform the connection
URL url = new URL( versionUrl );
HttpsURLConnection urlConnection = ( HttpsURLConnection ) url.openConnection();
urlConnection.setSSLSocketFactory(sslContext.getSocketFactory());
//urlConnection.setHostnameVerifier(hostnameVerifier); //Configure hostnameVerifier if needed
urlConnection.setConnectTimeout( 10000 );
InputStream in = urlConnection.getInputStream();
最后,您将拥有从here和here中提取的自定义X509ExtendedKeyManager的完整实现,该实现负责选择客户端证书.我已经提取了所需的代码. public static class KeyChainKeyManager extends X509ExtendedKeyManager {
private final String mClientAlias;
private final X509Certificate[] mCertificateChain;
private final PrivateKey mPrivateKey;
/**
* Builds an instance of a KeyChainKeyManager using the given certificate alias.
* If for any reason retrieval of the credentials from the system {@link android.security.KeyChain} fails,* a {@code null} value will be returned.
*/
public static KeyChainKeyManager fromAlias(Context context,String alias)
throws CertificateException {
X509Certificate[] certificateChain;
try {
certificateChain = KeyChain.getCertificateChain(context,alias);
} catch (KeyChainException e) {
throw new CertificateException(e);
} catch (InterruptedException e) {
throw new CertificateException(e);
}
PrivateKey privateKey;
try {
privateKey = KeyChain.getPrivateKey(context,alias);
} catch (KeyChainException e) {
throw new CertificateException(e);
} catch (InterruptedException e) {
throw new CertificateException(e);
}
if (certificateChain == null || privateKey == null) {
throw new CertificateException("Can't access certificate from keystore");
}
return new KeyChainKeyManager(alias,certificateChain,privateKey);
}
private KeyChainKeyManager(
String clientAlias,X509Certificate[] certificateChain,PrivateKey privateKey) {
mClientAlias = clientAlias;
mCertificateChain = certificateChain;
mPrivateKey = privateKey;
}
@Override
public String chooseClientAlias(String[] keyTypes,Principal[] issuers,Socket socket) {
return mClientAlias;
}
@Override
public X509Certificate[] getCertificateChain(String alias) {
return mCertificateChain;
}
@Override
public PrivateKey getPrivateKey(String alias) {
return mPrivateKey;
}
@Override
public final String chooseServerAlias( String keyType,Socket socket) {
// not a client SSLSocket callback
throw new UnsupportedOperationException();
}
@Override
public final String[] getClientAliases(String keyType,Principal[] issuers) {
// not a client SSLSocket callback
throw new UnsupportedOperationException();
}
@Override
public final String[] getServerAliases(String keyType,Principal[] issuers) {
// not a client SSLSocket callback
throw new UnsupportedOperationException();
}
}
}
我没有测试它.报告任何错误! (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
