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
댓글 없음:
댓글 쓰기