Android WebView가 HTTPS URL을로드하지 않음


91
public void onCreate(Bundle savedInstance)
{       
    super.onCreate(savedInstance);
    setContentView(R.layout.show_voucher);
    webView=(WebView)findViewById(R.id.webview);
    webView.getSettings().setJavaScriptEnabled(true);
    webView.getSettings().setBuiltInZoomControls(true);
    String url ="https://www.paymeon.com/Vouchers/?v=%C80%8D%B1x%D9%CFqh%FA%84%C35%0A%1F%CE&iv=%25%EE%BEi%F4%DAT%E1"
    //webView.loadUrl(url); // Not Working... Showing blank
    webView.loadUrl("http://www.yahoo.com"); // its working    
}

WebBView에서 URL을로드하려고하면 빈 화면 만 표시됩니다. Google.com 또는 yahoo.com을로드하면 정상적으로 작동합니다.


1
지금 확인했습니다. 그 후에 작동하지 않으면 다시 확인하십시오. webView.getSettings (). setUseWideViewPort (true); webView.getSettings (). setLoadWithOverviewMode (true);
ilango j 2011

답변:


155

이 링크를 방문하십시오 :

WebViewClient 구현에이 재정의 메서드를 추가합니다. Android SDK 2.2 (API 레벨 8) 이상으로 컴파일해야합니다. 이 메서드는 2.2 (API 레벨 8)부터 공개 SDK에 나타나지만 2.1, 1.6 및 1.5를 실행하는 장치에서 테스트했으며 해당 장치에서도 작동합니다 (따라서 동작은 모두 계속되었습니다).

 @Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
    handler.proceed(); // Ignore SSL certificate errors
}

이것은 당신을 도울 것입니다.


3
토론의 마지막 항목은 훌륭하게 작동했습니다. 매우 감사합니다.
Bill Lahti 2011

54
보안 경고 : 이렇게하면 처음에 SSL을 사용하는 목적이 완전히 무효화됩니다.
ereOn

8
이러지 마세요. 안전하지 않으며 Play 스토어에서 허용되지 않습니다.
Antimony

33
Google은 이제 위의 솔루션을 구현하는 사람에게 이메일을 보냅니다.Your app(s) listed at the end of this email have an unsafe implementation of the WebViewClient.onReceivedSslError handler. Specifically, the implementation ignores all SSL certificate validation errors, making your app vulnerable to man-in-the-middle attacks. Apps with vulnerabilities that expose users to risk of compromise may be considered Dangerous Products in violation of the Content Policy and section 4.4 of the Developer Distribution Agreement.
Gustavo

3
누구든지 Google 보안 경고를 해결하는 방법을 알고 있습니다. 그렇다면이 문제에 직면했기 때문에 알려주십시오.
Pratik Tank

49

다음은 도움이 될만한 작은 코드 샘플입니다.

먼저 WebViewClient를 확장하고 SSL 오류를 무시하도록 설정된 클래스를 만듭니다.

// SSL Error Tolerant Web View Client
private class SSLTolerentWebViewClient extends WebViewClient {

            @Override
            public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
                handler.proceed(); // Ignore SSL certificate errors
            }

}

그런 다음 웹보기 개체 (OnCreate () 메서드에서 시작됨)를 사용하여 웹보기 클라이언트를 재정의 클래스의 인스턴스로 설정합니다.

 mWebView.setWebViewClient(
                new SSLTolerentWebViewClient()
        );

2
이것은 Google 보안 경고를 제공합니다. WebViewClient.onReceivedSslError 핸들러의 안전하지 않은 구현입니다. 이 문제를 해결하는 방법을 알고 있습니까?
Pratik Tank

2
Google은 Playstore에서 앱을 Unsaif로 표시했습니다. SSL없이 어떻게 할 수 있습니까?
아제 디야

Super 메서드를 사용하지 마십시오. super.onReceivedSslError (view, handler, error);
Atul Bhardwaj 19

41

SSL 인증서 유효성 검사를 제대로 처리하고 새로운 보안 정책에 따라 Google의 애플리케이션 거부를 방지하려면 서버에서 제공 한 인증서가 예상을 충족 할 때마다 SslErrorHandler.proceed ()를 호출하도록 코드를 변경하고 그렇지 않으면 SslErrorHandler.cancel ()을 호출합니다.

예를 들어 사용자가 확인하고 Google이 더 이상 경고를 표시하지 않는 것처럼 보이도록 경고 대화 상자를 추가합니다.

    @Override
    public void onReceivedSslError(WebView view, final SslErrorHandler handler, SslError error) {
    final AlertDialog.Builder builder = new AlertDialog.Builder(this);
    String message = "SSL Certificate error.";
        switch (error.getPrimaryError()) {
            case SslError.SSL_UNTRUSTED:
                message = "The certificate authority is not trusted.";
                break;
            case SslError.SSL_EXPIRED:
                message = "The certificate has expired.";
                break;
            case SslError.SSL_IDMISMATCH:
                message = "The certificate Hostname mismatch.";
                break;
            case SslError.SSL_NOTYETVALID:
                message = "The certificate is not yet valid.";
                break;
        }
        message += " Do you want to continue anyway?";

        builder.setTitle("SSL Certificate Error");
        builder.setMessage(message);
    builder.setPositiveButton("continue", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            handler.proceed();
        }
    });
    builder.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            handler.cancel();
        }
    });
    final AlertDialog dialog = builder.create();
    dialog.show();
}

이 변경 후에는 경고가 표시되지 않습니다.


구현에서 onReceivedSslError 블록을 제거하면 어떻게됩니까?
비벡 신하

1
@VivekSinha는 handler.cancel (); 기본적으로.
Anant Shah

1
하지만 Google은 여전히 ​​같은 이유로 내 앱을 거부했습니다. 왜?
비벡 신하

@VivekSinha는 Play 스토어에서 앱 실행에 관한 해결책을 찾았습니까?
케샤

2
제안대로 onReceivedSslError 콜백을 구현했습니다. 나중에 앱이 성공적으로 게시되었습니다.
Vivek Sinha 2017 년

11

아래 코드를 제거하면 작동합니다.

 super.onReceivedSslError(view, handler, error);

훌륭합니다. 어떻게 작동했는지 설명해 주시겠습니까?
ARTH Tilva

3
Google 문서의 @ArthTilva : "기본 동작은로드를 취소하는 것입니다". super를 호출하면 나머지 메서드에 도달하기 전에 해당 기본 동작을 호출하게됩니다. developer.android.com/reference/android/webkit/…
Josh Laird

11

onReceivedSslError를 재정의하고 제거합니다.

super.onReceivedSslError (보기, 핸들러, 오류)

그리고 Google 보안을 해결하려면 :

setDomStorageEnabled (true);

전체 코드는 다음과 같습니다.

webView.enableJavaScript();
webView.getSettings().setDomStorageEnabled(true); // Add this
webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
webView.setWebViewClient(new WebViewClient(){
        @Override
        public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
            // DO NOT CALL SUPER METHOD
            super.onReceivedSslError(view, handler, error);
        }
    });

정말 감사합니다. super.onReceivedSslError (view, handler, error) 제거가 저에게 효과적이었습니다.
Däñish Shärmà

7

코드 줄을 복사하여 붙여 넣으십시오. 저를 믿으십시오. :) 생각하고 있습니다. ssl 오류가 발생합니다. onReceivedSslError 메서드를 재정의하고 super를 제거하면 super 메서드입니다. handler.proceed () 작성하면 오류가 해결됩니다.

    webView.setWebChromeClient(new WebChromeClient() {
        public void onProgressChanged(WebView view, int progress) {

            activity.setTitle("Loading...");
            activity.setProgress(progress * 100);

            if (progress == 100)
                activity.setTitle(getResources().getString(R.string.app_name));
        }
    });

    webView.setWebViewClient(new WebViewClient() {
        @Override
        public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
            Log.d("Failure Url :" , failingUrl);
        }

        @Override
        public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
            Log.d("Ssl Error:",handler.toString() + "error:" +  error);
            handler.proceed();
        }

        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            view.loadUrl(url);
            return true;
        }
    });
    webView.getSettings().setJavaScriptEnabled(true);
    webView.getSettings().setLoadWithOverviewMode(true);
    webView.getSettings().setUseWideViewPort(true);
    webView.getSettings().setDomStorageEnabled(true);
    webView.loadUrl(Constant.VIRTUALPOS_URL + "token=" + Preference.getInstance(getContext()).getToken() + "&dealer=" + Preference.getInstance(getContext()).getDealerCode());

감사. onReceivedSslError내 하루 저장에 handler.proceed () 호출
Tam Huynh

2
이렇게하면 (현재 2019 년 7 월) Google Play에서 신청을 거부합니다.
Alp Altunel

Google Play에 응용 프로그램이 너무 많아서 아직 앱이 거부되지 않습니다.
ozanurkan

1
2020 년 1 월 온-워드 거부 예정
John Ruban Singh

6

SSL URL을 처리하려면 방법 WebViewClient 클래스의 onReceivedSslError () . 다음은 예제입니다.

 webview.setWebViewClient(new WebViewClient() {
              ...
              ...
              ...

            @Override
            public void onReceivedSslError(WebView view, final SslErrorHandler handler, SslError error) {
                String message = "SSL Certificate error.";
                switch (error.getPrimaryError()) {
                    case SslError.SSL_UNTRUSTED:
                        message = "The certificate authority is not trusted.";
                        break;
                    case SslError.SSL_EXPIRED:
                        message = "The certificate has expired.";
                        break;
                    case SslError.SSL_IDMISMATCH:
                        message = "The certificate Hostname mismatch.";
                        break;
                    case SslError.SSL_NOTYETVALID:
                        message = "The certificate is not yet valid.";
                        break;
                }
                message += "\"SSL Certificate Error\" Do you want to continue anyway?.. YES";

                handler.proceed();
            }

        });

내 전체 예제는 https://github.com/Jorgesys/Android-WebView-Logging 에서 확인할 수 있습니다.

여기에 이미지 설명 입력


6

Google 보안을 해결하려면 다음과 같이하십시오.

맨 위로 줄 :

import android.webkit.SslErrorHandler;
import android.net.http.SslError;

암호:

class SSLTolerentWebViewClient extends WebViewClient {
    @Override
    public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
        if (error.toString() == "piglet")
            handler.cancel();
        else
            handler.proceed(); // Ignore SSL certificate errors
    }
}

2
저는 Android를 처음 사용합니다. 이거 어디에 넣어야하나요? :)
Gediminas

5

위의 답변을 따랐지만 여전히 https 요청 인 지불 게이트웨이를 통합 할 때 코드 아래에서 나를 위해 작동하지 않는 것 같습니다.

public class MainActivity extends Activity {

    WebView webView;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        webView = (WebView) findViewById(R.id.webView1);
        WebSettings settings = webView.getSettings();
        settings.setJavaScriptEnabled(true);
        settings.setDomStorageEnabled(true);
        webView.setWebViewClient(new MyWebViewClient());
        String postData = "amount=1000&firstname=mtetno&email=mttee@gmail.com&phone=2145635784&productinfo=android&surl=success.php"
                + "&furl=failure.php&lastname=qwerty&curl=dsdsd.com&address1=dsdsds&address2=dfdfd&city=dsdsds&state=dfdfdfd&"
                + "country=fdfdf&zipcode=123456&udf1=dsdsds&udf2=fsdfdsf&udf3=jhghjg&udf4=fdfd&udf5=fdfdf&pg=dfdf";
        webView.postUrl(
                "http://host/payment.php",
                EncodingUtils.getBytes(postData, "BASE64"));

    }

    private class MyWebViewClient extends WebViewClient {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            webView.loadUrl(url);
            return true;
        }

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

위의 코드는 webview에서 게시 요청을 수행하고 지불 게이트웨이로 리디렉션합니다.

설정 settings.setDomStorageEnabled(true);이 나를 위해 트릭을 해줬 으면 좋겠네요.


2
이 솔루션은 인증서 유효성 검사를 완전히 비활성화하여 중간자 (man-in-the-middle) 공격을 허용합니다. 이것은 특히 지불 게이트웨이의 경우 절대하지 말아야 할 일입니다.
Dirbaio

저에게 처음에는 webview가 콘텐츠를로드하지 않고 페이지의 배경 이미지 만로드했습니다. 방금 추가 한 후에는 webview.getSettings.setDomStorageEnabled(true);마술처럼 작동했습니다. 웹 페이지에서 일종의 HTML 5 API를 사용하고 있으므로 DomStorage를 사용하도록 설정하는 것이 효과적이었습니다.
Ishant Sagar

handler.proceed () 우회 SSL
존 루반 싱

Encodingutil.getbyte는 무엇입니까
Akash kumar

2

권장되는 접근 방식은

1. 슈퍼 메소드 호출 안함 (오버라이드 메소드에서 슈퍼 콜 제거)

2. 오류가 발생하면 SslErrorHandler.cancel () 메서드 를 호출하는 것이 좋습니다.

3. SSL 오류를 표시하라는 메시지를 표시하지 마십시오.

최고의 솔루션은 무엇입니까 ?? 이 재정의 방법 제거

@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler,SslError error) {

}

해결책을 요청하거나 제안하고 있습니까?
Dharman

저는이 접근 방식을 제안합니다
John Ruban Singh 19

@JohnRubanSingh 안녕하세요 John, 자산에서 JS 파일을로드하고 onPageFinished로 파일을로드하면 JS 내부에서 함수를 호출하고 있습니다. 그래서 webview.setWebViewClient (new ....)를 사용하고 있으므로 onReceivedSslError ()를 재정의하는 것이 필요합니까?
Shivam Sharma

이 코드는 내 APK를 거부합니다. 9 개월 이후에도이 코드는 거부를 일으키지 않고 갑자기 거부 r8에 직면합니다. switch (error.getPrimaryError ()) {case SslError.SSL_UNTRUSTED : handler.proceed (); 단절; case SslError.SSL_EXPIRED : case SslError.SSL_IDMISMATCH : case SslError.SSL_NOTYETVALID : case SslError.SSL_DATE_INVALID : case SslError.SSL_INVALID : 기본값 : handler.cancel (); 단절; }
Shivam Sharma

@JohnRubanSingh 제발 도와주세요. 느슨하게 참여할 수 있습니다.
Shivam Sharma

0

이 두 가지 속성을 설정하는 것만으로도 충분했고 보안 문제에 노출되지 않습니다.

 WebSettings settings = webView.getSettings();
    settings.setJavaScriptEnabled(true);
    settings.setDomStorageEnabled(true);

0

Java 코드에서 webview.getSettings (). setDomStorageEnabled (true) 줄을 사용하십시오 .

WebView webView = (WebView) findViewById(R.id.webview);    
webView.getSettings().setDomStorageEnabled(true);
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webView.loadUrl(yourUrl);

0

Google Play 스토어 외부에서 APK를 사용하려는 경우 (예 : 비공개) 다음과 같은 솔루션이 작동 할 수 있습니다.

    @Override
    public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
        /*...*/
        handler.proceed();
    }

추가적인 선택적 보안 계층을 추가하려는 경우 인증서 고정 을 사용할 수 있습니다 . IMHO 이것은 개인 또는 내부 사용을 위해 필요하지 않습니다.

Google Play 스토어에 앱을 게시하려는 경우 @Override onReceivedSslError (...) {...}를 피해야합니다. 특히 handler.proceed ()를 사용합니다. Google은이 코드 스 니펫을 찾고 handler.proceed ()를 사용하는 솔루션이 모든 종류의 내장 보안 메커니즘을 억제 하므로 앱을 확실히 거부합니다 .

그리고 브라우저가 https 연결에 대해 불평하지 않는다는 사실 때문에 SSL 인증서 자체가 전혀 신뢰된다는 것을 의미하지는 않습니다!

제 경우에는 SSL 인증서 체인 이 끊어졌습니다. SSL Checker를 사용 하거나 SSLLabs를 사용 하여 중간 수준의 문제를 빠르게 테스트 할 수 있습니다 . 그러나 어떻게 이런 일이 일어날 수 있는지 묻지 마십시오. 나는 전혀 단서가 없습니다.

어쨌든 SSL 인증서를 다시 설치 한 후 " WebView의 신뢰할 수없는 SSL 인증서 "와 관련된 모든 오류 가 마침내 사라졌습니다. 또한 onReceivedSslError (...)에 대한 @Override를 제거하고 handler.proceed ()를 제거 했으며 내 앱이 Google Play 스토어에서 다시 거부되지 않았습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.