-
-
Save demixdn/3886de5a71dc2812c8f4d27a248a506b to your computer and use it in GitHub Desktop.
package <you_package>.data.api; | |
import android.content.Context; | |
import android.support.annotation.NonNull; | |
import com.google.gson.ExclusionStrategy; | |
import com.google.gson.FieldAttributes; | |
import com.google.gson.Gson; | |
import com.google.gson.GsonBuilder; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.security.KeyManagementException; | |
import java.security.KeyStore; | |
import java.security.KeyStoreException; | |
import java.security.NoSuchAlgorithmException; | |
import java.security.cert.Certificate; | |
import java.security.cert.CertificateException; | |
import java.security.cert.CertificateFactory; | |
import java.util.concurrent.TimeUnit; | |
import javax.net.ssl.SSLContext; | |
import javax.net.ssl.TrustManagerFactory; | |
import io.realm.RealmObject; | |
import okhttp3.OkHttpClient; | |
import okhttp3.Request; | |
import okhttp3.logging.HttpLoggingInterceptor; | |
import retrofit2.GsonConverterFactory; | |
import retrofit2.Retrofit; | |
import retrofit2.RxJavaCallAdapterFactory; | |
import <you_package>.BuildConfig; | |
import <you_package>.utils.LogUtils; | |
public class ApiModule { | |
@NonNull | |
private final String baseUrl; | |
@NonNull | |
private static Gson gson; | |
@NonNull | |
private final OkHttpClient.Builder httpClientBuilder; | |
/** | |
* Create Rertofit params: logging, ssl connection and access token | |
* @param baseUrl endpoint of service | |
* @param authToken access token for connection, must be NULL in auth request | |
*/ | |
public ApiModule(@NonNull String baseUrl, @NonNull Context context, String authToken){ | |
this.baseUrl = baseUrl; | |
httpClientBuilder = new OkHttpClient.Builder().readTimeout(5, TimeUnit.SECONDS); | |
initGson(); | |
initHttpLogging(HttpLoggingInterceptor.Level.BODY); | |
initSSL(context); | |
initAuthToken(authToken); | |
} | |
private void initGson() { | |
GsonBuilder gsonBuilder = new GsonBuilder(); | |
gsonBuilder.setExclusionStrategies(new ExclusionStrategy() { | |
@Override | |
public boolean shouldSkipField(FieldAttributes f) { | |
return f.getDeclaringClass().equals(RealmObject.class); | |
} | |
@Override | |
public boolean shouldSkipClass(Class<?> clazz) { | |
return false; | |
} | |
}); | |
gson = gsonBuilder.create(); | |
} | |
private void initHttpLogging(HttpLoggingInterceptor.Level level) { | |
HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); | |
logging.setLevel(level); | |
if(BuildConfig.DEBUG) | |
httpClientBuilder.addInterceptor(logging); | |
} | |
/** | |
* ToDo modify this: set param is InputStream from certificate file,move beyond the context of the module | |
* @param context for read InputSream from raw resources | |
*/ | |
private void initSSL(@NonNull Context context) { | |
SSLContext sslContext = null; | |
try { | |
sslContext = createCertificate(context.getResources().openRawResource(R.raw.certificate)); | |
} catch (CertificateException | IOException | KeyStoreException | KeyManagementException | NoSuchAlgorithmException e) { | |
e.printStackTrace(); | |
} | |
if(sslContext!=null) | |
httpClientBuilder.sslSocketFactory(sslContext.getSocketFactory()); | |
} | |
public void initAuthToken(String authToken) { | |
LogUtils.E("initAuthToken - "+authToken); | |
if (authToken != null) { | |
httpClientBuilder.addInterceptor(chain -> { | |
Request original = chain.request(); | |
Request.Builder requestBuilder = original.newBuilder() | |
.header("Authorization", authToken) | |
.method(original.method(), original.body()); | |
Request request = requestBuilder.build(); | |
return chain.proceed(request); | |
}); | |
} | |
} | |
private SSLContext createCertificate(InputStream trustedCertificateIS) throws CertificateException, IOException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException { | |
CertificateFactory cf = CertificateFactory.getInstance("X.509"); | |
Certificate ca; | |
try { | |
ca = cf.generateCertificate(trustedCertificateIS); | |
} finally { | |
trustedCertificateIS.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); | |
return sslContext; | |
} | |
@NonNull | |
public RestAPI provideApiRx() | |
{ | |
return new Retrofit.Builder() | |
.baseUrl(baseUrl) | |
.addConverterFactory(GsonConverterFactory.create(gson)) | |
.addCallAdapterFactory(RxJavaCallAdapterFactory.create()) | |
.client(httpClientBuilder.build()) | |
.build() | |
.create(RestAPI.class); | |
} | |
@NonNull | |
public RestAPI provideApi() | |
{ | |
return new Retrofit.Builder() | |
.baseUrl(baseUrl) | |
.addConverterFactory(GsonConverterFactory.create(gson)) | |
.client(httpClientBuilder.build()) | |
.build() | |
.create(RestAPI.class); | |
} | |
} |
What's the format/how should the raw certificate look like?
What's the format/how should the raw certificate look like?
The raw certificate contents might look like this.
-----BEGIN CERTIFICATE----- MIIGJzCCBA+gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBsjELMAkGA1UEBhMCRlIx DzANBgNVBAgMBkFsc2FjZTETMBEGA1UEBwwKU3RyYXNib3VyZzEYMBYGA1UECgwP d3d3LmZyZWVsYW4ub3JnMRAwDgYDVQQLDAdmcmVlbGFuMS0wKwYDVQQDDCRGcmVl bGFuIFNhbXBsZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxIjAgBgkqhkiG9w0BCQEW E2NvbnRhY3RAZnJlZWxhbi5vcmcwHhcNMTIwNDI3MTAzMTE4WhcNMjIwNDI1MTAz MTE4WjB+MQswCQYDVQQGEwJGUjEPMA0GA1UECAwGQWxzYWNlMRgwFgYDVQQKDA93 d3cuZnJlZWxhbi5vcmcxEDAOBgNVBAsMB2ZyZWVsYW4xDjAMBgNVBAMMBWFsaWNl MSIwIAYJKoZIhvcNAQkBFhNjb250YWN0QGZyZWVsYW4ub3JnMIICIjANBgkqhkiG 9w0BAQEFAAOCAg8AMIICCgKCAgEA3W29+ID6194bH6ejLrIC4hb2Ugo8v6ZC+Mrc k2dNYMNPjcOKABvxxEtBamnSaeU/IY7FC/giN622LEtV/3oDcrua0+yWuVafyxmZ yTKUb4/GUgafRQPf/eiX9urWurtIK7XgNGFNUjYPq4dSJQPPhwCHE/LKAykWnZBX RrX0Dq4XyApNku0IpjIjEXH+8ixE12wH8wt7DEvdO7T3N3CfUbaITl1qBX+Nm2Z6 q4Ag/u5rl8NJfXg71ZmXA3XOj7zFvpyapRIZcPmkvZYn7SMCp8dXyXHPdpSiIWL2 uB3KiO4JrUYvt2GzLBUThp+lNSZaZ/Q3yOaAAUkOx+1h08285Pi+P8lO+H2Xic4S vMq1xtLg2bNoPC5KnbRfuFPuUD2/3dSiiragJ6uYDLOyWJDivKGt/72OVTEPAL9o 6T2pGZrwbQuiFGrGTMZOvWMSpQtNl+tCCXlT4mWqJDRwuMGrI4DnnGzt3IKqNwS4 Qyo9KqjMIPwnXZAmWPm3FOKe4sFwc5fpawKO01JZewDsYTDxVj+cwXwFxbE2yBiF z2FAHwfopwaH35p3C6lkcgP2k/zgAlnBluzACUI+MKJ/G0gv/uAhj1OHJQ3L6kn1 SpvQ41/ueBjlunExqQSYD7GtZ1Kg8uOcq2r+WISE3Qc9MpQFFkUVllmgWGwYDuN3 Zsez95kCAwEAAaN7MHkwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNT TCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFFlfyRO6G8y5qEFKikl5 ajb2fT7XMB8GA1UdIwQYMBaAFCNsLT0+KV14uGw+quK7Lh5sh/JTMA0GCSqGSIb3 DQEBBQUAA4ICAQAT5wJFPqervbja5+90iKxi1d0QVtVGB+z6aoAMuWK+qgi0vgvr mu9ot2lvTSCSnRhjeiP0SIdqFMORmBtOCFk/kYDp9M/91b+vS+S9eAlxrNCB5VOf PqxEPp/wv1rBcE4GBO/c6HcFon3F+oBYCsUQbZDKSSZxhDm3mj7pb67FNbZbJIzJ 70HDsRe2O04oiTx+h6g6pW3cOQMgIAvFgKN5Ex727K4230B0NIdGkzuj4KSML0NM slSAcXZ41OoSKNjy44BVEZv0ZdxTDrRM4EwJtNyggFzmtTuV02nkUj1bYYYC5f0L ADr6s0XMyaNk8twlWYlYDZ5uKDpVRVBfiGcq0uJIzIvemhuTrofh8pBQQNkPRDFT Rq1iTo1Ihhl3/Fl1kXk1WR3jTjNb4jHX7lIoXwpwp767HAPKGhjQ9cFbnHMEtkro RlJYdtRq5mccDtwT0GFyoJLLBZdHHMHJz0F9H7FNk2tTQQMhK5MVYwg+LIaee586 CQVqfbscp7evlgjLW98H+5zylRHAgoH2G79aHljNKMp9BOuq6SnEglEsiWGVtu2l hnx8SB3sVJZHeer8f/UQQwqbAO+Kdy70NmbSaqaVtp8jOxLiidWkwSyRTsuU6D8i DiH5uEqBXExjrj0FslxcVKdVj5glVcSmkLwZKbEU1OKwleT/iXFhvooWhQ== -----END CERTIFICATE-----
Note this is a sample.
Don't use it on production!
Thanks alot.