Выполнение запроса HTTPS с использованием Android Volley - программирование
Подтвердить что ты не робот

Выполнение запроса HTTPS с использованием Android Volley

Я пытаюсь сделать запрос 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: привязка доверия для путь сертификации не найден.

Следует отметить две точки:

  • Сертификат HTTPS действителен. Легко открывается без предупреждения в браузере.
  • Приведенный выше код отлично работает с HTTP-ссылками.

Мне действительно нужно знать, есть ли какие-либо переключатели/опции в структуре Android Volley, с помощью которых я успешно удалю URL HTTPS?

4b9b3361

Ответ 2

Возможно, эти коды ниже будут вам полезны:

1.Создайте класс HttpsTrustManager, который реализует X509TrustManager:

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.Добавьте HttpsTrustManager.allowAllSSL(), прежде чем сделать запрос https:

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);

Ответ 3

вы можете добавить этот класс и выполнить его из onCreate метода

new NukeSSLCerts().nuke();

он заставит залп доверять всем SSL-сертификатам.

Ответ 4

Пока единственный ответ говорит о добавлении ненадежного сертификата в качестве решения, но поскольку ваш браузер не жалуется, обычно означает, что Volley не может найти промежуточный сертификат, который завершает полную доверенную цепочку.

Это случилось со мной с сертификатами LetsEncrypt. В большинстве браузеров уже есть промежуточные сертификаты, поэтому в браузере все выглядит хорошо, но волейболу явно не хватало чего-то.

Решение
Добавьте промежуточный сертификат в конфигурацию вашего веб-сервера. Для Apache вы можете следовать этой ссылке:
https://access.redhat.com/solutions/43575

Для LetsEncrypt это именно этот файл: /etc/letsencrypt/live/your.website.com/chain.pem Итак, помимо ваших сертификатов и ключей, у вас уже есть работа, у вас теперь есть эта третья строка:

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

Просто добавив эту строку, перезапуск apache и Volley больше не жалуются, и вы не вводите никаких уязвимостей безопасности!

Ответ 5

Если вы используете залп и хотите 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);" с "RequestQueue queue = Volley.newRequestQueue(this, new HurlStack (null, getSocketFactory()));" по просьбе залпа.

Ответ 6

Я не смог открыть ссылку, предоставленную @Ogre_BGR, но при просмотре сети я нашел фактическую реализацию, выполненную в следующем smanikandan14 Github. Посмотрите на его объяснение SSl-подключения, чтобы больше узнать об этом.

Ответ 7

Это может произойти по нескольким причинам, включая:

  • CA, выдавший сертификат сервера, был неизвестен
  • Сертификат сервера не был подписан ЦС, но был сам подписан
  • В конфигурации сервера отсутствует промежуточный CA

Официальный документ от android

Решение: вы можете предоставить файл сертификата в запросе

Ответ 8

Если вы столкнетесь с такой проблемой, и вы используете Letsencrypt для своего SSL и 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);