我有一个需要连接到具有SSL证书的服务器的Android应用程序。
我对此很陌生。你能告诉我相信证书的步骤吗?
我正在为我的Rest Client使用Retrofit库
答案 0 :(得分:1)
如果要使用自签名证书,请使用以下代码(它将创建一个不验证证书链的信任管理器):
public class RestModule {
private RestAdapter mRestAdapter;
private RaasService mRaasService;
private String mAccessToken;
public RestModule(final Context context, final String endPoint)
{
init(context, endPoint);
}
public RestModule(final Context context, final String endPoint, final String accessToken) {
mAccessToken = accessToken;
init(context, endPoint);
}
public void init(final Context context, final String endPoint) {
final MyPreferences preference = MyPreferences.getInstance();
final RestAdapter.Builder builder = new RestAdapter.Builder().setLogLevel(RestAdapter.LogLevel.FULL)
.setRequestInterceptor(new RequestInterceptor() {
@Override
public void intercept(RequestFacade requestFacade) {
if (mAccessToken == null) {
mAccessToken = preference.getCurrentAccountAccessToken();
}
requestFacade.addHeader("secretToken", mAccessToken);
requestFacade.addHeader("Content-Type", "application/json;charset=UTF-8");
}
})
.setEndpoint(endPoint);
builder.setClient(new OkClient(getUnsafeOkHttpClient()));
mRestAdapter = builder.build();
}
private static OkHttpClient getUnsafeOkHttpClient() {
try {
// Create a trust manager that does not validate certificate chains
final TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
}
};
// Install the all-trusting trust manager
final SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
// Create an ssl socket factory with our all-trusting manager
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setSslSocketFactory(sslSocketFactory);
okHttpClient.setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
okHttpClient.setConnectTimeout(30, TimeUnit.SECONDS);
okHttpClient.setReadTimeout(30, TimeUnit.SECONDS);
return okHttpClient;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public RaasService getService() {
if (mRaasService == null) {
mRaasService = mRestAdapter.create(RaasService.class);
}
return mRaasService;
}
}
要使用您的SSL证书,请使用以下方法代替getUnsafeOkHttpClient:
public static OkHttpClient trustcert(Context context){
OkHttpClient okHttpClient = new OkHttpClient();
try {
KeyStore ksTrust = KeyStore.getInstance("BKS");
InputStream instream = context.getResources().openRawResource(R.raw.mykeystore);
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;
}
您可以在https://viksaaskool.wordpress.com/2015/01/12/ssl-android-and-retrofit-some-frustration-might-occur/
找到更多详情答案 1 :(得分:1)
以下是具有适当信任存储的previously posted answer:
public class RestModule {
private RestAdapter mRestAdapter;
private RaasService mRaasService;
private String mAccessToken;
public RestModule(final Context context, final String endPoint)
{
init(context, endPoint);
}
public RestModule(final Context context, final String endPoint, final String accessToken) {
mAccessToken = accessToken;
init(context, endPoint);
}
public void init(final Context context, final String endPoint) {
final MyPreferences preference = MyPreferences.getInstance();
final RestAdapter.Builder builder = new RestAdapter.Builder().setLogLevel(RestAdapter.LogLevel.FULL)
.setRequestInterceptor(new RequestInterceptor() {
@Override
public void intercept(RequestFacade requestFacade) {
if (mAccessToken == null) {
mAccessToken = preference.getCurrentAccountAccessToken();
}
requestFacade.addHeader("secretToken", mAccessToken);
requestFacade.addHeader("Content-Type", "application/json;charset=UTF-8");
}
})
.setEndpoint(endPoint);
builder.setClient(new OkClient(getPinnedOkHttpClient(context)));
mRestAdapter = builder.build();
}
private static OkHttpClient getPinnedOkHttpClient(Context context) {
try {
final SSLContext sslContext = getSslContext(context);
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
// Create an ssl socket factory with our all-trusting manager
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setSslSocketFactory(sslSocketFactory);
okHttpClient.setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
okHttpClient.setConnectTimeout(30, TimeUnit.SECONDS);
okHttpClient.setReadTimeout(30, TimeUnit.SECONDS);
return okHttpClient;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private SSLContext getSslContext(Context context) throws Exception {
KeyStore trustStore = loadTrustStore(context);
String algotithmName = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(algotithmName);
trustManagerFactory.init(trustStore);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
return sslContext;
}
private KeyStore loadTrustStore(Context context) throws Exception {
KeyStore trustStore = KeyStore.getInstance("BKS");
InputStream trustStoreStream = context.getResources().getAssets().open("trust.bks");
trustStore.load(trustStoreStream, "password".toCharArray());
return trustStore;
}
public RaasService getService() {
if (mRaasService == null) {
mRaasService = mRestAdapter.create(RaasService.class);
}
return mRaasService;
}
}
您必须将服务器证书放在BKS密钥库中,并使用trust.bks
作为信任存储区的密码,放入assets
文件夹中名为password
的文件中。在此情况下,在代码中使用(公开)已知密码是没有问题的,因为信任存储中没有存储单个保密字节,只保留公知的服务器证书。
This SO answer告诉您如何从服务器证书创建BKS密钥库。