웹구간 보안을 위해 SSL을 적용하려면 인증서를 생성해서 웹서버에 설치/설정해주고 브라우저에서는 "https" 프로토콜로 접속하면 됩니다. 그러나 만약 인증서가 Verisign 등 신뢰된 기관(root CA)에서 서명된 인증서가 아니라면, 브라우저는 사용자에게 보안 경고창을 보여주어 웹페이지를 볼 건지 말건지 물어봅니다.


root CA로부터 서명된 인증서라면 이런 경고창 없이 페이지 내용이 바로 보여집니다(참고로 특정 모바일기기에서 어떤 인증기관의 인증서를 root CA로 인식하는지는 http://www.ssltest.net/ 사이트에서 테스트 가능합니다).

root CA로부터 서명을 받기 위한 비용은 대략 1년에 수 십만원이기 때문에 가난한 프로젝트 또는 개인들은 root CA 서명이 아닌 자체(self) 서명된 인증서를 사용할 수밖에 없습니다. 문제는 이렇게 셀프 서명된 인증서는 공식적으로는 신뢰할 수 없으므로 위와 같은 보안 경고창이 뜬다는 것이죠.
사실 보안 경고창이 뜬다고 해도 사용자에게 "계속" 버튼을 누르도록 교육시키면 그리 큰 문제는 아닙니다. 그러나 폰갭에서 똑같은 페이지를 불러온다면 어떤 일이 벌어질까요?

loadUrl("https://yourserver.com/some/page.html");


웁스.. 기대와 달리 그냥 텅빈 화면만 나옵니다.-.-


공백 화면이 나오는 이유는 신뢰되지 않은 인증서인 경우 android.webkit.WebViewClient에서 아래와 같이 페이지로딩 작업을 cancel시키기 때문입니다.

public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
    handler.cancel();
}


자 이제 원인을 알았으니 해결해보죠.

먼저 SSL에러가 발생하더라도 페이지 로딩을 계속 진행하도록 onReceivedSslError() 메소드를 재정의한 클래스를 만듭니다.(DroidGap을 상속한 Activity의 inner 클래스로 정의)

private class MyGapViewClient extends GapViewClient {
    public MyGapViewClient(DroidGap ctx) {
        super(ctx);
    }

   @Override
   public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
        handler.proceed();  //SSL 에러가 발생해도 계속 진행!
    }
}


이렇게 만든 MyGapViewClient 클래스를 onCreate()에서 아래처럼 세팅해줍니다.

public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   … …
   super.init();
   this.setWebViewClient(this.appView, new MyGapViewClient(this)); 
   … …
   loadUrl("https://yourserver.com/some/page.html");
}

 
빌드하고 앱을 다시 실행해보면 정상적으로 SSL보안이 적용된 웹페이지가 뜨는 것을 확인할 수 있습니다.
Posted by 에코지오
,