我正在尝试用我编写的Android应用中的HTTPS连接替换当前工作的HTTP连接。HTTPS连接的附加安全性是必需的,因此我不能忽略此步骤。
我有以下内容:
SSLSocketFactory.getSocketFactory()
连接正常,但是客户端证书是此应用程序规范的必需部分,因此:javax.net.ssl.SSLPeerUnverifiedException: No peer certificate
当我尝试与我的自定义连接时,客户端会产生异常SSLSocketFactory
,但我不确定原因为何。在互联网上搜索各种解决方案后,该例外似乎有点模棱两可。这是客户端的相关代码:
SSLSocketFactory socketFactory = null;
public void onCreate(Bundle savedInstanceState) {
loadCertificateData();
}
private void loadCertificateData() {
try {
File[] pfxFiles = Environment.getExternalStorageDirectory().listFiles(new FileFilter() {
public boolean accept(File file) {
if (file.getName().toLowerCase().endsWith("pfx")) {
return true;
}
return false;
}
});
InputStream certificateStream = null;
if (pfxFiles.length==1) {
certificateStream = new FileInputStream(pfxFiles[0]);
}
KeyStore keyStore = KeyStore.getInstance("PKCS12");
char[] password = "somePassword".toCharArray();
keyStore.load(certificateStream, password);
System.out.println("I have loaded [" + keyStore.size() + "] certificates");
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, password);
socketFactory = new SSLSocketFactory(keyStore);
} catch (Exceptions e) {
// Actually a bunch of catch blocks here, but shortened!
}
}
private void someMethodInvokedToEstablishAHttpsConnection() {
try {
HttpParams standardParams = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(standardParams, 5000);
HttpConnectionParams.setSoTimeout(standardParams, 30000);
SchemeRegistry schRegistry = new SchemeRegistry();
schRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
schRegistry.register(new Scheme("https", socketFactory, 443));
ClientConnectionManager connectionManager = new ThreadSafeClientConnManager(standardParams, schRegistry);
HttpClient client = new DefaultHttpClient(connectionManager, standardParams);
HttpPost request = new HttpPost();
request.setURI(new URI("https://TheUrlOfTheServerIWantToConnectTo));
request.setEntity("Some set of data used by the server serialized into string format");
HttpResponse response = client.execute(request);
resultData = EntityUtils.toString(response.getEntity());
} catch (Exception e) {
// Catch some exceptions (Actually multiple catch blocks, shortened)
}
}
我已经验证过,是的,的确keystore加载了证书并且对此感到满意。
关于阅读HTTPS / SSL连接所缺少的内容,我有两种理论,但这确实是我的首次尝试,因此我对解决此问题的实际需求感到有些困惑。
据我所知,第一种可能性是我需要使用设备的信任库配置此SSLSocketFactory,设备的信任库包括所有标准的中间和端点证书颁发机构。也就是说,设备的默认设置是SSLSocketFactory.getSocketFactory()
将一些CA集合加载到工厂的信任库中,该信任库用于在服务器发送其证书时信任服务器,这就是我的代码失败的原因,因为我没有正确加载信任库。如果这是真的,我将如何最好地加载此数据?
第二种可能性是由于客户证书是自签名的(或由内部证书颁发机构颁发的,如果我错了,请更正我,但出于此处的所有意图和目的,它们实际上是同一件事) 。实际上,我缺少
此 信任库,并且基本上,我需要为服务器提供一种使用内部CA验证证书的方法,并且还需要验证此内部CA实际上是 “可信任的”
。如果这是真的,那么我到底在寻找什么样的东西?我已经看到一些对此的参考,这使我相信这可能是我的问题,如此处所示,但我确实不确定。如果这确实是我的问题,那么我将向维护内部CA的人员提出什么要求,然后如何将其添加到我的代码中,以便HTTPS连接正常工作?
第三个也是希望不太可能的解决方案是,我在这里的某些地方完全错了,错过了关键的步骤,或者完全忽略了我目前不了解的HTTPS /
SSL部分。如果是这样,您能不能给我提供一些指导,以便我可以去学习我需要学习的内容?
谢谢阅读!
我认为这确实是问题。
据我所知,第一种可能性是我需要使用设备的信任库配置此SSLSocketFactory,设备的信任库包括所有标准的中间和端点证书颁发机构
如果这是真的,我将如何最好地加载此数据?
尝试这样的操作(您需要让套接字工厂使用此默认信任管理器):
X509TrustManager manager = null;
FileInputStream fs = null;
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
try
{
fs = new FileInputStream(System.getProperty("javax.net.ssl.trustStore"));
keyStore.load(fs, null);
}
finally
{
if (fs != null) { fs.close(); }
}
trustManagerFactory.init(keyStore);
TrustManager[] managers = trustManagerFactory.getTrustManagers();
for (TrustManager tm : managers)
{
if (tm instanceof X509TrustManager)
{
manager = (X509TrustManager) tm;
break;
}
}
编辑: 在这里使用代码之前,请先看Pooks的回答。听起来现在有更好的方法可以做到这一点。
问题内容: 我可以使用curl发出GET请求-> 我如何在节点中使用相同。我尝试了请求,超级代理,但无法通过证书。 提前致谢! 问题答案: 这对我有用 -
问题内容: 我还很陌生,对于使用证书进行身份验证时客户端应该显示的内容有些困惑。 我正在编写一个Java客户端,该客户端需要对POST特定对象进行简单的数据处理URL。那部分工作正常,唯一的问题是应该完成。该部分相当容易处理(无论是使用Java的内置HTTPS支持还是使用Java的内置支持),但是我一直坚持使用客户端证书进行身份验证。我注意到这里已经存在一个非常类似的问题,我还没有尝试使用我的代码
问题内容: 我需要导入证书,以便向Spring Boot应用程序中的外部服务发出http请求。 我该如何设置Spring Boot来做到这一点? 那里有很多信息,但我发现所有这些都令人困惑。似乎我可能只需要创建类似“ truststore.jks”密钥库的内容并导入正确的证书,然后将一些条目添加到我的application.properties中即可。 问题答案: 打开您的终端或 回答所有问题。在
我的连接代码如下所示: 干杯,马尔辛
我正在努力做一些基本的事情,但我的头脑还没有完全清醒过来。我有一个spring boot应用程序,它应该公开一个rest url。 我是这样做的: 正如您所见,它使用的是另一个服务,我正试图用一个外部客户机实现该服务: 界面看起来像: 当MdmhClient在调用: 我知道要解决这个问题,我需要将证书导入jre。我正在运行Intellij IDE,并将项目的jdk路径设置为: 我还通过firefo
问题内容: 我正在一个需要客户端和服务器证书认证的Android应用程序上工作。我创建了一个SSLClient类,该类在常规的台式机Java SE 6上运行良好。我将其移至Android项目中,并收到以下错误:“找不到KeyStore JKS实现”。 我已经在网上看了一下,似乎有可能Android上不支持Java Keystore(太棒了!),但是我感觉还不止如此,因为我发现的示例代码都没有类似于