ces*_*rds 61 java retrofit okhttp
我正在为拥有自签名SSL证书的服务器的客户工作.
我使用包装的OkHttp客户端使用Retrofit + CustomClient:
RestAdapter restAdapter = new RestAdapter.Builder().setEndpoint(Config.BASE_URL + Config.API_VERSION)
.setClient(new CustomClient(new OkClient(), context))
.build();
Run Code Online (Sandbox Code Playgroud)
OkHttp默认支持调用自签名SSL证书服务器吗?
顺便说说.哪个客户端默认使用Retrofit?我认为这是OkHttp,但当我研究了一点时,我意识到我需要导入OkHttp依赖项
And*_*rov 79
是的,它确实.
Retrofit允许您设置自定义HTTP客户端,该客户端根据您的需要进行配置.
至于自签名SSL证书,这里有一个讨论.该链接包含用于将自签名SLL添加到Android DefaultHttpClient
并将此客户端加载到Retrofit的代码示例.
如果您需要OkHttpClient
接受自签名SSL,则需要javax.net.ssl.SSLSocketFactory
通过setSslSocketFactory(SSLSocketFactory sslSocketFactory)
方法传递自定义实例.
获得套接字工厂的最简单方法是从这里javax.net.ssl.SSLContext
讨论得到一个.
以下是配置OkHttpClient的示例:
OkHttpClient client = new OkHttpClient();
KeyStore keyStore = readKeyStore(); //your method to obtain KeyStore
SSLContext sslContext = SSLContext.getInstance("SSL");
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, "keystore_pass".toCharArray());
sslContext.init(keyManagerFactory.getKeyManagers(),trustManagerFactory.getTrustManagers(), new SecureRandom());
client.setSslSocketFactory(sslContext.getSocketFactory());
Run Code Online (Sandbox Code Playgroud)
OkHttpClient client = new OkHttpClient.Builder()
.sslSocketFactory(sslContext.getSocketFactory())
.build();
Run Code Online (Sandbox Code Playgroud)
在client
这里现在配置为从您使用证书KeyStore
.但是,它只会信任您的证书,KeyStore
并且不会信任其他任何内容,即使您的系统默认信任它们.(如果您只有自签名证书,KeyStore
并尝试通过HTTPS连接到Google主页,您将获得SSLHandshakeException
).
您可以KeyStore
从文件中获取实例,如文档中所示:
KeyStore readKeyStore() {
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
// get user password and file input stream
char[] password = getPassword();
java.io.FileInputStream fis = null;
try {
fis = new java.io.FileInputStream("keyStoreName");
ks.load(fis, password);
} finally {
if (fis != null) {
fis.close();
}
}
return ks;
}
Run Code Online (Sandbox Code Playgroud)
如果你在Android上,你可以把它放在res/raw
文件夹中,并从一个Context
实例使用它
fis = context.getResources().openRawResource(R.raw.your_keystore_filename);
Run Code Online (Sandbox Code Playgroud)
有几个关于如何创建密钥库的讨论.例如这里
GR *_*voy 12
还有一点要注意,如果你在设备上预装了 CA,你可以用 OKHttp 进行常规的 https 调用,而没有特殊的 ssl 箍。关键是将网络安全配置添加到您的清单中。
我知道这样做的关键是我遇到了以下异常。
“未找到认证路径的信任锚。 ”
这是来自 Google 的一篇关于如何配置它的好文章。 https://developer.android.com/training/articles/security-config
这是我的 network_security_config.xml 的示例
<?xml version="1.0" encoding="UTF-8" ?>
<network-security-config>
<base-config cleartextTrafficPermitted="false">
<trust-anchors>
<certificates src="user"/>
<certificates src="system"/>
</trust-anchors>
</base-config>
</network-security-config>
Run Code Online (Sandbox Code Playgroud)
对于okhttp3.OkHttpClient版本com.squareup.okhttp3:okhttp:3.2.0您必须使用以下代码:
import okhttp3.Call;
import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.Headers;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
......
OkHttpClient.Builder clientBuilder = client.newBuilder().readTimeout(LOGIN_TIMEOUT_SEC, TimeUnit.SECONDS);
boolean allowUntrusted = true;
if ( allowUntrusted) {
Log.w(TAG,"**** Allow untrusted SSL connection ****");
final TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
@Override
public X509Certificate[] getAcceptedIssuers() {
X509Certificate[] cArrr = new X509Certificate[0];
return cArrr;
}
@Override
public void checkServerTrusted(final X509Certificate[] chain,
final String authType) throws CertificateException {
}
@Override
public void checkClientTrusted(final X509Certificate[] chain,
final String authType) throws CertificateException {
}
}};
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
clientBuilder.sslSocketFactory(sslContext.getSocketFactory());
HostnameVerifier hostnameVerifier = new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
Log.d(TAG, "Trust Host :" + hostname);
return true;
}
};
clientBuilder.hostnameVerifier( hostnameVerifier);
}
final Call call = clientBuilder.build().newCall(request);
Run Code Online (Sandbox Code Playgroud)
从我们的应用程序获取OkHttpClient 3.0实例的两种方法,这些实例可以从密钥库中识别您的自签名证书(使用Android项目“原始”资源文件夹中准备好的pkcs12证书文件):
private static OkHttpClient getSSLClient(Context context) throws
NoSuchAlgorithmException,
KeyStoreException,
KeyManagementException,
CertificateException,
IOException {
OkHttpClient client;
SSLContext sslContext;
SSLSocketFactory sslSocketFactory;
TrustManager[] trustManagers;
TrustManagerFactory trustManagerFactory;
X509TrustManager trustManager;
trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(readKeyStore(context));
trustManagers = trustManagerFactory.getTrustManagers();
if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
throw new IllegalStateException("Unexpected default trust managers:" + Arrays.toString(trustManagers));
}
trustManager = (X509TrustManager) trustManagers[0];
sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[]{trustManager}, null);
sslSocketFactory = sslContext.getSocketFactory();
client = new OkHttpClient.Builder()
.sslSocketFactory(sslSocketFactory, trustManager)
.build();
return client;
}
/**
* Get keys store. Key file should be encrypted with pkcs12 standard. It can be done with standalone encrypting java applications like "keytool". File password is also required.
*
* @param context Activity or some other context.
* @return Keys store.
* @throws KeyStoreException
* @throws CertificateException
* @throws NoSuchAlgorithmException
* @throws IOException
*/
private static KeyStore readKeyStore(Context context) throws
KeyStoreException,
CertificateException,
NoSuchAlgorithmException,
IOException {
KeyStore keyStore;
char[] PASSWORD = "12345678".toCharArray();
ArrayList<InputStream> certificates;
int certificateIndex;
InputStream certificate;
certificates = new ArrayList<>();
certificates.add(context.getResources().openRawResource(R.raw.ssl_pkcs12));
keyStore = KeyStore.getInstance("pkcs12");
for (Certificate certificate : certificates) {
try {
keyStore.load(certificate, PASSWORD);
} finally {
if (certificate != null) {
certificate.close();
}
}
}
return keyStore;
}
Run Code Online (Sandbox Code Playgroud)
我遇到了同样的问题,我用okhttp客户端修复了它,如下所示:
1.) 将certificate
文件添加到src/main/res/raw/
,其中包含以下内容:
-----BEGIN CERTIFICATE-----
...=
-----END CERTIFICATE-----
Run Code Online (Sandbox Code Playgroud)
2.) 实例化 okHttpClient:
OkHttpClient client = new OkHttpClient.Builder()
.sslSocketFactory(getSslContext(context).getSocketFactory())
.build();
Run Code Online (Sandbox Code Playgroud)
3.) 这里是使用的getSslContext(Context context)
方法:
SSLContext getSslContext(Context context) throws Exception {
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); // "BKS"
ks.load(null, null);
InputStream is = context.getResources().openRawResource(R.raw.certificate);
String certificate = Converter.convertStreamToString(is);
// generate input stream for certificate factory
InputStream stream = IOUtils.toInputStream(certificate);
// CertificateFactory
CertificateFactory cf = CertificateFactory.getInstance("X.509");
// certificate
Certificate ca;
try {
ca = cf.generateCertificate(stream);
} finally {
is.close();
}
ks.setCertificateEntry("my-ca", ca);
// TrustManagerFactory
String algorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
// Create a TrustManager that trusts the CAs in our KeyStore
tmf.init(ks);
// Create a SSLContext with the certificate that uses tmf (TrustManager)
sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), new SecureRandom());
return sslContext;
}
Run Code Online (Sandbox Code Playgroud)
如果需要向 SslContext 添加多个证书,这里是解决方案。
归档时间: |
|
查看次数: |
58290 次 |
最近记录: |