HurlStack 설정
좀 더 살펴보니, 좀 더 간략한 방법이 있어서 적어놓는다. 아래 소개한 것들과 대부분의 글들이 apache httpclient 를 사용하고 있는데, 개인적으로 익숙하지도 않고, Android 6.0 에서는 사라진다고 한다.그래서 volley 의 HurlStack class 를 보고 있으니, SSL 설정을 할 수 있게 되어 있었다. constructor 의 인자로 SSLSocketFactory 를 넘겨주면 된다.
// kotlin source
/**
* Created by namh on 2015-10-29.
*/
object MyVolleyRequestQueue{
var _ctx by Delegates.notNull<Context>()
public fun init(context: Context){
_ctx = context
}
var _requestQueue: RequestQueue? = null
public fun getRequestQueue(): RequestQueue? {
if (_requestQueue == null) {
val cache = DiskBasedCache(_ctx.cacheDir, 10 * 1024 * 1024)
// HurlStack with SocketFactory
val network = BasicNetwork(HurlStack(null, getSSLSocketFactory()))
_requestQueue = RequestQueue(cache, network)
_requestQueue!!.start()
}
return _requestQueue
}
fun getSSLSocketFactory(): SSLSocketFactory {
// SSLContext
val sc = SSLContext.getInstance("TLS");
sc.init(null, null, null)
return sc.getSocketFactory()
}
}
Self-signed 인증서
test 등을 위해 self-signed certificate 을 이용할 때는 이야기가 조금 복잡해 진다.자세한 부분에 대해서는 아래 code 들을 참고하자.
- http://developer.android.com/intl/ko/training/articles/security-ssl.html#UnknownCa : 이 code 가 가장 명확한 듯 하다.
- http://chariotsolutions.com/blog/post/https-with-client-certificates-on/
/ github source : 좀 난해?하지만, key 에 대한 처리등을 보기 좋을 듯 하다. - java - Using client/server certificates for two way authentication SSL socket on Android - Stack Overflow
HttpsURLConnection.setDefaultHostnameVerifier
여기와 여기에서 HttpsURLConnection.setDefaultHostnameVerifier 를 사용하는 방법을 확인할 수 있다. 이방법을 적용 해보지는 않았지만 훨씬 편할 듯 하다.kotlin source
kotlin 소스이지만, 이해하는데에 큰 무리는 없을 것이다.var _requestQueue: RequestQueue? = null
public fun getRequestQueue(): RequestQueue? {
if (_requestQueue == null) {
val cache = DiskBasedCache(_ctx.cacheDir, 10 * 1024 * 1024)
val network = BasicNetwork(HurlStack(null, getSSLSocketFactory()))
_requestQueue = RequestQueue(cache, network)
_requestQueue!!.start()
}
return _requestQueue
}
fun getSSLSocketFactory(): SSLSocketFactory {
// TODO : delete this part, after have a certificate
val sc = SSLContext.getInstance("TLS");
sc.init(null, _getTrustManager(), null)
return sc.socketFactory
}
fun _getTrustManager(): Array<TrustManager> {
val assetManager = _ctx.getAssets()
val certKeyis= assetManager.open("dummy-cert-hbwhale.der")
// Load CAs from an InputStream
// (could be from a resource or ByteArrayInputStream or ...)
var ca: Certificate? = null
val cf = CertificateFactory.getInstance("X.509")
try{
ca = cf.generateCertificate(certKeyis)
}finally{
certKeyis.close()
}
// Create a KeyStore containing our trusted CAs
val keyStoreType = KeyStore.getDefaultType();
val keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
// Create a TrustManager that trusts the CAs in our KeyStore
val tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
val tmFactory = TrustManagerFactory.getInstance(tmfAlgorithm);
tmFactory.init(keyStore);
return tmFactory.getTrustManagers()
}
여기서는 ref. 1 에 나와있는 tutorial 을 따라 해 본다. source 도 ref. 1 의 소스 를 실행하는 것에 중점을 두기로 한다.
좀 더 간단한 소스가 있어서 이 소스를 좀 확인 해 보자.
keystore 만들기
먼저 사용할 keystore 와 certificate 을 만들어야 한다.BKS format keystore 바로 만들기
- android - How to create a BKS (BouncyCastle) format Java Keystore that contains a client certificate chain - Stack Overflow : bks library 를 받아서 설정하고 바로 keystore 만들 때 bks keystore 를 만드는 방법을 알려준다.
JKS format 으로 keystore 만들기
key 만들기는 아래 글을 참고하자.- keytool 을 이용해서 keystore 만들기
- keytool 유틸리티를 사용하여 인증서 생성 (Sun Java System Application Server 9.1 관리 설명서)
keytool 을 이용해서 .jks keystore 와 .cert 를 만들자.
BSK 로 변환
그리고 이렇게 만든 .jks 를 .bks 로 변환해야 한다. 이것은 portecle 을 이용하면 된다. 자세한 방법은 여기 를 참고하자.안드로이드 https 에서 개인 인증서 추가
아래 링크는 안드로이드에서 https 를 사용하려고 할 때, 자신이 만든 인증서로 test 를 할 경우들이 많이 있다. 이 경우에 어떤 식으로 프로그래밍을 하는지 알려준다.Android project 에 넣기
이제 이 .bsk 를 android project 의 res/raw 에 넣자.- <android project>\app\src\main\res\raw\mybks.bks
소스 수정
이제- android_volley_examples/src/com/github/volley_examples/Act_SsSslHttpClient.java
에서 노란색 부분을 수정하자.
- R.raw.test : .bsk 파일 이름
- "test123" : keystore 의 password
- 44401 : https 서버의 port
- "https://ave.bolyartech.com:44401/https_test.html" : 서버의 url
public class Act_SsSslHttpClient extends Activity {
...
protected void onCreate(Bundle savedInstanceState) {
...
btnSimpleRequest.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// Replace R.raw.test with your keystore
InputStream keyStore = getResources().openRawResource(R.raw.test);
// Usually getting the request queue shall be in singleton like in {@see Act_SimpleRequest}
// Current approach is used just for brevity
RequestQueue queue = Volley
.newRequestQueue(Act_SsSslHttpClient.this,
new ExtHttpClientStack(new SslHttpClient(keyStore, "test123", 44401)));
StringRequest myReq = new StringRequest(Method.GET,
"https://ave.bolyartech.com:44401/https_test.html",
createMyReqSuccessListener(),
createMyReqErrorListener());
queue.add(myReq);
}
});
}
이제 준비는 끝났다. server 부분은 알아서 준비하자. 이제 example 을 실행해 보면서 동작하는지를 확인하면 될 듯 하다.
See Also
- http://stackoverflow.com/questions/2012497/accepting-a-certificate-for-https-on-android
- http://en.wikipedia.org/wiki/Bouncy_Castle_(cryptography) : Bouncy Castle 은 암호화에 사용되는 api 들의 집합, Java 와 C# 의 API 들이라고 한다.
- http://stackoverflow.com/questions/6866447/keytool-error-java-security-keystoreexception-bks-not-found : storetype BKS 와 관련된 설명
- Trusting all certificates using HttpClient over HTTPS
Reference
- Using Android Volley With Self-Signed SSL Certificate - Ogre's Lab : self-signed certificate 으로 구현
- moltak/android-https-volley · GitHub
댓글 없음:
댓글 쓰기