2013-10-26 3 views
1

У меня есть сервер, обслуживающий порт 9443. Он использует сертификат ssl, подписанный godaddy для «example.com». Я пытаюсь подключиться к URL, как:Получение 400 плохих запросов при использовании SSL на порту, отличном от 443?

https://example.com:9443/api/v1/foo 

и отлично работает с ИОС приложения я написал, и настольных браузеров. Если я попытаюсь подключиться к телефону Android, я получаю ответ на 400 запросов. Я попробовал то же самое через хром для андроида, это дает мне:

ERR_TUNNEL_CONNECTION_FAILED 

Сервер также прослушивает порт 443, используя самозаверяющий сертификат, и андроид клиент работает нормально там (я нужен дополнительный код там, чтобы мое приложение доверяло самозаверяющему сертификату).

Есть ли ограничение в android, где https должен использовать порт 443? Я думал, что, поскольку я использую законный сертификат ssl, мне не нужен какой-либо пользовательский код, чтобы заставить приложение доверять сертификату. Мой код подключения:

HttpParams params = new BasicHttpParams(); 
DefaultHttpClient client = new DefaultHttpClient(params); 
HttpResponse response = client.execute(request); 
Result result = new Result(response.getStatusLine().getStatusCode()); 

response.getStatusLine().getStatusCode(); // 400 
response.getStatusLine().toString(); // HTTP/1.1 400 Bad Request 

Благодаря

+0

Вы доступ через прокси-сервер, случайно? –

ответ

1

Две возможности, я думаю.

Поиск ERR_TUNNEL_CONNECTION_FAILED android приводит меня к this page, где автор утверждает:

Android по неизвестной причине не позволит вам использовать нестандартные портов для SSL (т.е. только порт 443 работает при использовании HTTPS)

Я подтвердил это, попробовав веб-сайт SSL на порту 2000, используя мои wifes iphone на AT & T. Конечно, это сработало нормально. Так что его не AT & T. Также стоит отметить, что он отлично работает на Wi-Fi.

Надеюсь, это всего лишь ошибка и будет исправлена ​​в будущем.

Однако this site утверждает, что при доступе к сайту через прокси-сервер возникает ошибка. Возможно, у вас может быть настроен прокси-сервер на вашем телефоне Android, который он пытается каким-то образом использовать.

Самый простой способ узнать, в каком мире вы находитесь, будет проверяться с помощью другого телефона Android, если он у вас есть.

+0

Huh what heck - если я подключаюсь к домашнему wifi здесь (полностью отделен от моей серверной машины), то соединение проходит через порт на порт 9443. Если я отключу Wi-Fi и просто подключусь через данные AT & T, Вы получите ошибку 400. – user291701

+0

Это довольно убедительное доказательство для случая с Android-ошибкой. (Из любопытства, интересно, что произойдет, если вы привяжетесь к телефону Android и используете браузер для настольных компьютеров ...) –

+0

О, и я не подключен к любому прокси на телефоне Android. – user291701

0

Это может помочь вам

public HttpClient getNewHttpClient() { 
     try { 
      KeyStore trustStore = KeyStore.getInstance(KeyStore 
        .getDefaultType()); 
      trustStore.load(null, null); 

      SSLSocketFactory sf = new MySSLSocketFactory(trustStore); 
      sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); 

      HttpParams params = new BasicHttpParams(); 
      HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); 
      HttpProtocolParams.setContentCharset(params, HTTP.UTF_8); 

      SchemeRegistry registry = new SchemeRegistry(); 
      registry.register(new Scheme("http", PlainSocketFactory 
        .getSocketFactory(), 80)); 
      registry.register(new Scheme("https", sf, 443)); 

      ClientConnectionManager ccm = new ThreadSafeClientConnManager(
        params, registry); 

      return new DefaultHttpClient(ccm, params); 
     } catch (Exception e) { 
      return new DefaultHttpClient(); 
     } 
    } 



public class MySSLSocketFactory extends SSLSocketFactory { 
    SSLContext sslContext = SSLContext.getInstance("TLS"); 

    public MySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException { 
     super(truststore); 

     TrustManager tm = new X509TrustManager() { 
      public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { 
      } 

      public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { 
      } 

      public X509Certificate[] getAcceptedIssuers() { 
       return null; 
      } 
     }; 

     sslContext.init(null, new TrustManager[] { tm }, 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

Используйте этот Httpclient вместо deafault. –

+0

Это, по сути, то, что я делаю для самозаверяющего сертификата сегодня. Но я хотел отойти от этого к подлинному сертификату. – user291701

+0

На самом деле это не работает при использовании порта, отличного от 443. – user291701

Смежные вопросы