[컴][안드로이드] volley 에서 https, ssl 사용하기




HurlStack 설정

좀 더 살펴보니, 좀 더 간략한 방법이 있어서 적어놓는다. 아래 소개한 것들과 대부분의 글들이 apache httpclient 를 사용하고 있는데, 개인적으로 익숙하지도 않고, Android 6.0 에서는 사라진다고 한다.

그래서 volley 의 HurlStack class 를 보고 있으니, SSL 설정을 할 수 있게 되어 있었다. constructor 의 인자로 SSLSocketFactory 를 넘겨주면 된다.
아래 간략한 kotlin code 이다. 참고하기 바란다.

// 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 들을 참고하자.

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 바로 만들기



JKS format 으로 keystore 만들기

key 만들기는 아래 글을 참고하자.
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


소스 수정

이제

에서 노란색 부분을 수정하자.
  • 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

  1. http://stackoverflow.com/questions/2012497/accepting-a-certificate-for-https-on-android
  2. http://en.wikipedia.org/wiki/Bouncy_Castle_(cryptography) : Bouncy Castle 은 암호화에 사용되는 api 들의 집합, Java 와 C# 의 API 들이라고 한다.
  3. http://stackoverflow.com/questions/6866447/keytool-error-java-security-keystoreexception-bks-not-found : storetype BKS 와 관련된 설명
  4. Trusting all certificates using HttpClient over HTTPS




Reference

  1. Using Android Volley With Self-Signed SSL Certificate - Ogre's Lab : self-signed certificate 으로 구현
  2. moltak/android-https-volley · GitHub





댓글 없음:

댓글 쓰기