web-dev-qa-db-ja.com

Android Volleyを使用してHTTPSリクエストを行う

私はこのコードを使用してhttpsリクエストを作成しようとしています:

RequestQueue queue = Volley.newRequestQueue(getApplicationContext());
request = new Request<String>(Request.Method.GET,"https://devblahblahblah.com/service/etc",errListener);

しかし、私はこのエラーを受け取っています:

com.Android.volley.NoConnectionError:javax.net.ssl.SSLHandshakeException:Java.security.cert.CertPathValidatorException:証明書パスのトラストアンカーが見つかりません。

注意すべき2つのポイント:

  1. HTTPS証明書は有効です。ブラウザで警告なしに簡単に開きます。
  2. 上記のコードは、HTTPリンクで正常に機能します。

Android VolleyフレームワークにHTTPS URLを正常にヒットするスイッチ/オプションがあるかどうかを実際に知る必要がありますか?

50
Abdullah Shoaib

おそらく、以下のこれらのコードは役に立つでしょう:

1. _X509TrustManager_を実装するHttpsTrustManagerクラスを作成します。

_public class HttpsTrustManager implements X509TrustManager {

    private static TrustManager[] trustManagers;
    private static final X509Certificate[] _AcceptedIssuers = new X509Certificate[]{};

    @Override
    public void checkClientTrusted(
            Java.security.cert.X509Certificate[] x509Certificates, String s)
            throws Java.security.cert.CertificateException {

    }

    @Override
    public void checkServerTrusted(
            Java.security.cert.X509Certificate[] x509Certificates, String s)
            throws Java.security.cert.CertificateException {

    }

    public boolean isClientTrusted(X509Certificate[] chain) {
        return true;
    }

    public boolean isServerTrusted(X509Certificate[] chain) {
        return true;
    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return _AcceptedIssuers;
    }

    public static void allowAllSSL() {
        HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {

            @Override
            public boolean verify(String arg0, SSLSession arg1) {
                return true;
            }

        });

        SSLContext context = null;
        if (trustManagers == null) {
            trustManagers = new TrustManager[]{new HttpsTrustManager()};
        }

        try {
            context = SSLContext.getInstance("TLS");
            context.init(null, trustManagers, new SecureRandom());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }

        HttpsURLConnection.setDefaultSSLSocketFactory(context
                .getSocketFactory());
    }

}
_

2. httpsリクエストを行う前にHttpsTrustManager.allowAllSSL()を追加します。

_HttpsTrustManager.allowAllSSL();
String  tag_string_req = "string_req";
StringRequest strReq = new StringRequest(Request.Method.POST,
        your_https_url, new Response.Listener<String>() {
    @Override
    public void onResponse(String response) {
        Log.d(TAG, "response :"+response);
    }
}, new Response.ErrorListener() {
    @Override
    public void onErrorResponse(VolleyError error) {
        VolleyLog.d(TAG, "Error: " + error.getMessage());
    }
}){
    @Override
    protected Map<String, String> getParams() {
        Map<String, String> params = new HashMap<String, String>();
        params.put("username", "max");
        params.put("password", "123456");
        return params;
    }
};
AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
_
52
MaxMxx

このクラスを追加 し、onCreateメソッドから実行できます

new NukeSSLCerts().nuke();

すべてのSSL証明書を信頼するようにボレーを行います。

10
Samrat Das

ボレーを使用していて、HTTPS要求またはSSL認定サービスを使用する場合は、次の最も簡単な方法を選択できます。->

手順-> 1. .cerファイルをres/raw /フォルダーに保存します。

手順-> 2.この方法を使用して、.cerファイル名を.cerファイルに置き換え、ホスト名も置き換えます。

private SSLSocketFactory getSocketFactory() {

    CertificateFactory cf = null;
    try {

        cf = CertificateFactory.getInstance("X.509");
        InputStream caInput = getResources().openRawResource(R.raw.cert_name);
        Certificate ca;
        try {

            ca = cf.generateCertificate(caInput);
            Log.e("CERT", "ca=" + ((X509Certificate) ca).getSubjectDN());
        } finally {
            caInput.close();
        }


        String keyStoreType = KeyStore.getDefaultType();
        KeyStore keyStore = KeyStore.getInstance(keyStoreType);
        keyStore.load(null, null);
        keyStore.setCertificateEntry("ca", ca);


        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(keyStore);


        HostnameVerifier hostnameVerifier = new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {

                Log.e("CipherUsed", session.getCipherSuite());
                return hostname.compareTo("10.199.89.68")==0; //The Hostname of your server.

            }
        };


        HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
        SSLContext context = null;
        context = SSLContext.getInstance("TLS");

        context.init(null, tmf.getTrustManagers(), null);
        HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());

        SSLSocketFactory sf = context.getSocketFactory();


        return sf;

    } catch (CertificateException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (KeyStoreException e) {
        e.printStackTrace();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (KeyManagementException e) {
        e.printStackTrace();
    }

    return  null;
}

ステップ-> 3.この行を置き換えます「RequestQueue queue = Volley.newRequestQueue(this);」 with "RequestQueue queue = Volley.newRequestQueue(this、new HurlStack(null、getSocketFactory()));"ボレーのリクエストで。

3
Chinki Sai

これまでのところ、唯一の答えは信頼できない証明書をソリューションとして追加することについて語っていますが、ブラウザーは文句を言わないので、通常、完全な信頼されたチェーンを完了する中間証明書が見つからないことを意味します。

LetsEncrypt証明書で私に起こりました。ほとんどのブラウザはすでに中間証明書を持っているので、ブラウザ上ではすべてが正常に見えますが、ボレーは何かを見逃していたようです。

解決策
中間証明書をWebサーバー設定に追加します。 Apacheの場合、次のリファレンスを参照できます。
https://access.redhat.com/solutions/43575

LetsEncryptの場合、具体的には次のファイルです:/etc/letsencrypt/live/your.website.com/chain.pemしたがって、CertificateFileとKeyFileに加えて、すでに3番目の行が機能しているはずです。

SSLCertificateChainFile /etc/letsencrypt/live/your.website.com/chain.pem

その行を追加するだけで、ApacheとVolleyを再起動しても文句は言われず、セキュリティの脆弱性も発生しませんでした!

3
Lappro

@Ogre_BGRによって提供されたリンクを開くことができませんでしたが、ネットを閲覧していると、次の smanikandan14 Github で実際の実装が行われていることがわかりました SSl-connectionの説明 でさらに理解する。

1
laaptu

これは、次のようないくつかの理由で発生する可能性があります。

  • サーバー証明書を発行したCAは不明でした
  • サーバー証明書はCAによって署名されていませんが、自己署名されています
  • サーバー構成に中間CAがありません

Androidの公式ドキュメント

解決策:リクエスト内で証明書ファイルを提供できます

0
Din Islam Milon

このような問題に遭遇し、SSLにLetsencryptを使用し、Webサーバーにnode.jsを使用する場合は、これを試してください。このようなものがあると仮定します。行を追加することでこれを修正しましたconst chain = fs ...これが役に立てば幸いです

...
const app = express();
const privateKey  = fs.readFileSync('ssl/privkey.pem', 'utf8');
const certificate = fs.readFileSync('ssl/cert.pem', 'utf8');
const chain = fs.readFileSync('ssl/chain.pem', 'utf8');
const credentials = {key: privateKey, cert: certificate, ca: chain};
...
var httpsServer = https.createServer(credentials, app);
0
nada