2015-06-18 2 views
7

Я использую Volley в Android для выполнения запросов на приложение. К сожалению, я получаю следующее сообщение об ошибке:Исключение SSL при использовании Volley

com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x61e15f78: Failure in SSL library, usually a protocol error 
    error:1407743E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert inappropriate fallback (external/openssl/ssl/s23_clnt.c:744 0x5b647c58:0x00000000) 

Я использую два Fragments, внутри ViewPager, что запросить их содержание во время onResume. URL-адрес запросов в основном одинаковый, но для параметра запроса (который задает тип содержимого, например, тренд против горячего).

Адрес указан в форме https://host/api/content?type={hot/trending}. Авторизация выполняется через заголовок запроса.

Странная часть об этом исключении состоит в том, что только один из двух запросов терпит неудачу, и время от времени оно меняется. После того, как я добавил задержку между ними, исключение прекратилось (странно указывая на какое-то состояние гонки?). Но это кажется плохим обходным решением, и я бы хотел решить это правильно.

Любые мысли о том, что может быть причиной этого?

EDIT:

Запрос создается стандартным способом, используя синглтона обеспечение очереди следующим образом:

final RequestQueue requestQueue = RequestQueueSingleton.getInstance(getActivity()).getRequestQueue(); 
final GsonRequestGet<SearchApiWrapper> gsonRequest = new GsonRequestGet<>(clazz, url,successListener, errorListener); 
gsonRequest.setRetryPolicy(new DefaultRetryPolicy(3000, 3, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT)); 
gsonRequest.setTag(mTag); 
requestQueue.add(gsonRequest); 

А вот класс синглтон:

public class RequestQueueSingleton { 

    private static RequestQueueSingleton mInstance; 
    private RequestQueue mRequestQueue; 
    private Context mContext; 

    public RequestQueueSingleton(Context context) { 
     mContext = context; 
     mRequestQueue = getRequestQueue(); 
    } 

    /** 
    * Returns a instance of this singleton 
    */ 
    public static synchronized RequestQueueSingleton getInstance(Context context) { 
     if (mInstance == null) { 
      mInstance = new RequestQueueSingleton(context); 
     } 
     return mInstance; 
    } 

    /** 
    * Returns instance of the request queue 
    */ 
    public RequestQueue getRequestQueue() { 
     if (mRequestQueue == null) { 
      mRequestQueue = Volley.newRequestQueue(mContext.getApplicationContext()); 
     } 
     return mRequestQueue; 
    } 
} 
+0

Как вы создаете свой запрос на Volley RequestQueue? – GuilhE

+0

Взгляните на это http://stackoverflow.com/questions/22564317/https-support-for-volley-android-networking-library – EE66

+0

@GuilhE Я отредактировал код, чтобы добавить логику создания requestQueue и как я ее использую. –

ответ

3

После наши комментарии, может быть, это может вам помочь:

Ваш requestQueue:

static { 
    requestQueue = Volley.newRequestQueue(Application.getContext(), new HurlStack(null, ClientSSLSocketFactory.getSocketFactory())); 
} 

ClientSSLSocketFactory:

public class ClientSSLSocketFactory extends SSLCertificateSocketFactory { 
    private SSLContext sslContext; 

    public static SSLSocketFactory getSocketFactory(){ 
     try 
     { 
      X509TrustManager tm = new X509TrustManager() { 
       public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException {} 

       public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException {} 

       public X509Certificate[] getAcceptedIssuers() { 
        return null; 
       } 
      }; 
      sslContext = SSLContext.getInstance("TLS"); 
      sslContext.init(null, new TrustManager[] { tm }, null); 

      SSLSocketFactory ssf = ClientSSLSocketFactory.getDefault(10000, new SSLSessionCache(Application.getInstance())); 

      return ssf; 
     } catch (Exception ex) { 
      return null; 
     } 
    } 

    @Override 
    public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException { 
     return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose); 
    } 

    @Override 
    public Socket createSocket() throws IOException { 
     return sslContext.getSocketFactory().createSocket(); 
    } 
} 
+0

Это принимает все сертификаты, правильно? –

+0

Ну, я бы сказал, да, потому что, когда мы делаем sslContext.init (null, new TrustManager [] {tm}, null); 'мы используем наш' tm', который не имеет реализации. Я не испытал это, я как только смогу. – GuilhE

+0

К сожалению, проблема продолжает происходить, реже, но происходит все еще. Любые идеи о том, что может быть причиной? –

1

Добавить импортируют statments.

import javax.net.ssl.TrustManager; 
import javax.net.ssl.HostnameVerifier; 
import javax.net.ssl.HttpsURLConnection; 
import javax.net.ssl.SSLContext; 
import javax.net.ssl.SSLSession; 
import javax.net.ssl.X509TrustManager; 
import java.security.cert.X509Certificate; 
import java.util.ResourceBundle; 

и добавьте следующий код, прежде чем сделать сетевой вызов.

TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { 
     public java.security.cert.X509Certificate[] getAcceptedIssuers() { 
      return null; 
     } 
     public void checkClientTrusted(X509Certificate[] certs, String authType) { 
     } 
     public void checkServerTrusted(X509Certificate[] certs, String authType) { 
     } 
    } }; 
    SSLContext sc = null; 
    try { 
     sc = SSLContext.getInstance("SSL"); 
    } catch (NoSuchAlgorithmException e) { 
     e.printStackTrace(); 
    } 
    try { 
     sc.init(null, trustAllCerts, new java.security.SecureRandom()); 
    } catch (KeyManagementException e) { 
     e.printStackTrace(); 
    } 
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); 
    // Create all-trusting host name verifier 
    HostnameVerifier allHostsValid = new HostnameVerifier() { 
     public boolean verify(String hostname, SSLSession session) { 
      return true; 
     } 
    }; 
    // Install the all-trusting host verifier 
    HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);