更新时间:2021-07-08 22:36:42
免责声明:此答案来自 2015 年 7 月,并从那时起使用 Retrofit 和 OkHttp.
查看此链接了解更多关于 Retrofit v2 和 这个用于当前的 OkHttp 方法.
DISCLAIMER: this answer is from Jul 2015 and uses Retrofit and OkHttp from that time.
Check this link for more info on Retrofit v2 and this one for the current OkHttp methods.
好的,我使用 Android 开发者指南.
就像 OP 一样,我正在尝试使用 Retrofit 和 OkHttp 来连接到启用了自签名 SSL 的服务器.
Just as OP, I'm trying to use Retrofit and OkHttp to connect to a self-signed SSL-enabled server.
这是使事情正常工作的代码(我已经删除了 try/catch 块):
Here's the code that got things working (I've removed the try/catch blocks):
public static RestAdapter createAdapter(Context context) {
// loading CAs from an InputStream
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream cert = context.getResources().openRawResource(R.raw.my_cert);
Certificate ca;
try {
ca = cf.generateCertificate(cert);
} finally { cert.close(); }
// creating a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
// creating a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
// creating an SSLSocketFactory that uses our TrustManager
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);
// creating an OkHttpClient that uses our SSLSocketFactory
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setSslSocketFactory(sslContext.getSocketFactory());
// creating a RestAdapter that uses this custom client
return new RestAdapter.Builder()
.setEndpoint(UrlRepository.API_BASE)
.setClient(new OkClient(okHttpClient))
.build();
}
为了帮助调试,我还在 RestAdapter 创建命令中添加了 .setLogLevel(RestAdapter.LogLevel.FULL)
,我可以看到它连接并从服务器获取响应.
To help in debugging, I also added .setLogLevel(RestAdapter.LogLevel.FULL)
to my RestAdapter creation commands and I could see it connecting and getting the response from the server.
只需要保存在 main/res/raw
中的原始 .crt 文件..crt 文件,也就是证书,是使用 openssl
创建证书时创建的两个文件之一.通常,它是一个 .crt 或 .cert 文件,而另一个是 .key 文件.
All it took was my original .crt file saved in main/res/raw
.
The .crt file, aka the certificate, is one of the two files created when you create a certificate using openssl
. Generally, it is a .crt or .cert file, while the other is a .key file.
Afaik,.crt 文件是您的公钥,.key 文件是您的私钥.
Afaik, the .crt file is your public key and the .key file is your private key.
如我所见,您已经有一个 .cert 文件,它是相同的,因此请尝试使用它.
As I can see, you already have a .cert file, which is the same, so try to use it.
PS:对于那些将来阅读它并且只有 .pem 文件的人,根据 这个答案,您只需要将其转换为另一个:
PS: For those that read it in the future and only have a .pem file, according to this answer, you only need this to convert one to the other:
openssl x509 -outform der -in your-cert.pem -out your-cert.crt
PS²:对于那些根本没有任何文件的人,您可以使用以下命令(bash)从任何服务器中提取公钥(又名证书):
PS²: For those that don't have any file at all, you can use the following command (bash) to extract the public key (aka certificate) from any server:
echo -n | openssl s_client -connect your.server.com:443 |
sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > ~/my_cert.crt
只需替换 your.server.com
和端口(如果它不是标准的 HTTPS)并为要创建的输出文件选择一个有效的路径.
Just replace the your.server.com
and the port (if it is not standard HTTPS) and choose a valid path for your output file to be created.