我正在创建一个android应用程序,它使用https
与服务器通信。我使用retrofit
和OkHttp
进行请求。这些对于标准的http
请求很好。以下是我遵循的步骤。
**第一步:**使用命令从服务器获取证书文件
echo -n | openssl s_client -connect api.****.tk:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > gtux.cert
**步骤2:**使用以下命令将证书转换为BKS格式
keytool -importcert -v -trustcacerts -file "gtux.cert" -alias imeto_alias -keystore "my_keystore.bks" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "bcprov-jdk16-146.jar" -storetype BKS
它要求我输入密码,文件成功创建。
步骤3:
创建一个OkHttpClient并使用它发出https请求
public class MySSLTrust {
public static OkHttpClient trustcert(Context context){
OkHttpClient okHttpClient = new OkHttpClient();
try {
KeyStore ksTrust = KeyStore.getInstance("BKS");
InputStream instream = context.getResources().openRawResource(R.raw.my_keystore);
ksTrust.load(instream, "secret".toCharArray());
// TrustManager decides which certificate authorities to use.
TrustManagerFactory tmf = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ksTrust);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);
okHttpClient.setSslSocketFactory(sslContext.getSocketFactory());
} catch (KeyStoreException | IOException | NoSuchAlgorithmException | CertificateException | KeyManagementException e) {
e.printStackTrace();
}
return okHttpClient;
}
}
步骤4:
必须创建RestAdapter
RestAdapter.Builder()
.setRequestInterceptor(intercept)
.setEndpoint("https://api.****.tk")
.setClient(new OkClient(this))
.setLogLevel(RestAdapter.LogLevel.FULL)
.setLog(new AndroidLog("RETROFIT"))
.build();
但最后当运行应用程序时,它扔给我CertPathValidatorException : Trust anchor for certificate path not found
。请帮助我解决这个问题。谢谢。
**其他失败尝试:**尝试在我的Xperia Z2中安装证书,它说文件已安装,但当我运行应用程序时,会抛出相同的异常。
错误日志这里是我执行时得到的错误日志...
Error Log
贴在那里,以便阅读。
9条答案
按热度按时间f1tvaqid1#
免责声明:此答案来自2015年7月,并使用当时的Retrofit和OkHttp。
查看this link以了解有关Retrofit v2的更多信息,并查看此版本以了解当前的OkHttp方法。
好吧,我得到了它的工作使用Android开发人员指南.
就像OP一样,我尝试使用Retrofit和OkHttp连接到自签名的SSL服务器。
下面是让事情工作的代码(我已经删除了try/catch块):
为了帮助调试,我还将
.setLogLevel(RestAdapter.LogLevel.FULL)
添加到RestAdapter创建命令中,我可以看到它连接并从服务器获取响应。只需要我原来保存在
main/res/raw
中的**.crt文件。.crt文件,也就是证书,是使用openssl
创建证书时创建的两个文件之一。一般情况下,它是.crt或.cert文件,而另一个是.key文件。当然,.crt文件是您的公钥**,.key文件是您的私钥。
正如我所看到的,您已经有了一个**.cert**文件,这是相同的,所以请尝试使用它。
PS:对于以后读到的,只有.pem文件的用户,根据this answer,只需要这个就可以进行转换:
**PS²:**对于那些没有任何文件的用户,您可以使用以下命令(bash)从任何服务器提取公钥(又名证书):
只需替换
your.server.com
和端口(如果不是标准HTTPS),并为要创建的输出文件选择一个有效的路径。y53ybaqx2#
要解决
CertPathValidatorException
问题,请使用从https://mobikul.com/android-retrofit-handling-sslhandshakeexception/复制的以下代码-guz6ccqo3#
这是Kotlin版本。Okhttp 4.9.0
Thank you:)
raogr8fs4#
我不使用Retrofit,对于OkHttp,这里是对我有效的自签名证书的唯一解决方案:
1.像Gowtham的问题一样,从我们的网站获取证书,并将其放入项目的 res/raw 目录:
1.使用Paulo answer设置ssl工厂(现在使用 OkHttpClient.Builder()),但不创建RestAdapter。
1.然后添加the following解决方案来修复:*SSLPeerUnverifiedException:主机名未验证 *
因此,Paulo的代码(在 sslContext 初始化之后)的结尾看起来像下面这样:
xriantvc5#
改造2.3.0
zsbz8rwp6#
您正在将cert转换为BKS Keystore,为什么不直接使用
.cert
,从https://developer.android.com/training/articles/security-ssl.html:nqwrtyyt7#
在Kotlin中实现:改造2.3.0
}
ylamdve68#
经过长时间的研究和挖掘太深,我发现在Android的证书钉的解决方案,是的,它不同于iOS,我们需要一个证书本身,但在Android中,我们只需要一个散列引脚,就是这样。
如何获取证书的hash pin?
最初只是使用一个错误的散列引脚和您的java类将抛出一个错误与正确的散列引脚或引脚链,只需复制和粘贴到您的代码,这就是它。
这个解决方案解决了我的问题:https://stackoverflow.com/a/45853669/3448003
t5zmwmid9#
根据哈尼的回答,它对我来说工作得很好。但是如果你得到编译错误,你需要修复一件事。
将
okHttpClient.hostnameVerifier {HostnameVerifier { _, _ -> true } }
更改为okHttpClient.hostnameVerifier { _, _ -> true }
和函数