¿Cómo hacer un HTTPS POST de Android?

Quiero hacer un HTTPS post método para enviar algunos datos de mi aplicación Android a mi sitio web.

HttpURLConnection primero HttpURLConnection y funciona bien con mi URL HTTP. Mi sitio web de producción está en HTTPS y quiero enviar el mismo POST usando HttpsURLConnection . ¿Puede alguien ayudarme a usar la clase correctamente?

Encontré alguna fuente en este enlace :

 KeyStore keyStore = ...; TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509"); tmf.init(keyStore); SSLContext context = SSLContext.getInstance("TLS"); context.init(null, tmf.getTrustManagers(), null); URL url = new URL("https://www.example.com/"); HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection(); urlConnection.setSSLSocketFactory(context.getSocketFactory()); InputStream in = urlConnection.getInputStream(); 

¿Cuál debe ser el valor de KeyStore keyStore = ...; ?

Intenté enviar los datos usando la misma HttpURLConnection , pero estoy viendo algunos datos del POST se pierde o en el error.

He intentado el método de esta pregunta . Estoy pegando mi código abajo

 String urlParameters="dateTime=" + URLEncoder.encode(dateTime,"UTF-8")+ "&mobileNum="+URLEncoder.encode(mobileNum,"UTF-8"); URL url = new URL(myurl); HttpsURLConnection conn; conn=(HttpsURLConnection)url.openConnection(); // Create the SSL connection SSLContext sc; sc = SSLContext.getInstance("TLS"); sc.init(null, null, new java.security.SecureRandom()); conn.setSSLSocketFactory(sc.getSocketFactory()); conn.setConnectTimeout(HTTP_CONNECT_TIME_OUT); conn.setReadTimeout(HTTP_READ_TIME_OUT); //set the output to true, indicating you are outputting(uploading) POST data conn.setDoOutput(true); //once you set the output to true, you don't really need to set the request method to post, but I'm doing it anyway conn.setRequestMethod("POST"); conn.setFixedLengthStreamingMode(urlParameters.getBytes().length); conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); PrintWriter out = new PrintWriter(conn.getOutputStream()); out.print(urlParameters); out.close(); InputStream is = conn.getInputStream(); BufferedReader in = new BufferedReader(new InputStreamReader(is)); String inputLine; while ((inputLine = in.readLine()) != null) { response += inputLine; } 

El error que estoy recibiendo está abajo:

 05-12 19:36:10.758: W/System.err(1123): java.io.FileNotFoundException: https://www.myurl.com/fms/test 05-12 19:36:10.758: W/System.err(1123): at libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:177) 05-12 19:36:10.758: W/System.err(1123): at libcore.net.http.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:270) 05-12 19:36:10.758: W/System.err(1123): at .httpRequest(SMSToDBService.java:490) 05-12 19:36:10.758: W/System.err(1123): at com..access$0(SMSToDBService.java:424) 05-12 19:36:10.758: W/System.err(1123): at com.$ChildThread$1.handleMessage(SMSToDBService.java:182) 05-12 19:36:10.758: W/System.err(1123): at android.os.Handler.dispatchMessage(Handler.java:99) 05-12 19:36:10.758: W/System.err(1123): at android.os.Looper.loop(Looper.java:156) 05-12 19:36:10.758: W/System.err(1123): at com.$ChildThread.run(SMSToDBService.java:303) 

Puede usar las CA predeterminadas que se definen en el dispositivo android, que está bien para cualquier web pública.

Si tiene un certificado autofirmado, puede aceptar todos los certificados (riesgosos, abiertos a ataques de intermediario) o crear su propio TrustManagerFactory , algo fuera de este ámbito.

He aquí un código para usar las CAs predeterminadas para una llamada de POST de https:

 private InputStream getInputStream(String urlStr, String user, String password) throws IOException { URL url = new URL(urlStr); HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); // Create the SSL connection SSLContext sc; sc = SSLContext.getInstance("TLS"); sc.init(null, null, new java.security.SecureRandom()); conn.setSSLSocketFactory(sc.getSocketFactory()); // Use this if you need SSL authentication String userpass = user + ":" + password; String basicAuth = "Basic " + Base64.encodeToString(userpass.getBytes(), Base64.DEFAULT); conn.setRequestProperty("Authorization", basicAuth); // set Timeout and method conn.setReadTimeout(7000); conn.setConnectTimeout(7000); conn.setRequestMethod("POST"); conn.setDoInput(true); // Add any data you wish to post here conn.connect(); return conn.getInputStream(); } 

Para leer la respuesta:

  String result = new String(); InputStream is = getInputStream(urlStr, user, password); BufferedReader in = new BufferedReader(new InputStreamReader(is)); String inputLine; while ((inputLine = in.readLine()) != null) { result += inputLine; } 

Usted puede echar un vistazo a esta pregunta que le pregunté hace unos días:

Cambiar la solicitud de publicación HTTP a HTTPS:

He proporcionado allí una solución que trabajó para mí, que básicamente acepta cualquier certificado autofirmado. Como se ha dicho aquí esta solución no es recomendable, ya que no es seguro y abierto a un hombre en el medio ataques.

Aquí está el código:

EasySSLSocketFactory:

 public class EasySSLSocketFactory implements SocketFactory, LayeredSocketFactory { private SSLContext sslcontext = null; private static SSLContext createEasySSLContext() throws IOException { try { SSLContext context = SSLContext.getInstance("TLS"); context.init(null, new TrustManager[] { new EasyX509TrustManager(null) }, null); return context; } catch (Exception e) { throw new IOException(e.getMessage()); } } private SSLContext getSSLContext() throws IOException { if (this.sslcontext == null) { this.sslcontext = createEasySSLContext(); } return this.sslcontext; } /** * @see org.apache.http.conn.scheme.SocketFactory#connectSocket(java.net.Socket, java.lang.String, int, * java.net.InetAddress, int, org.apache.http.params.HttpParams) */ public Socket connectSocket(Socket sock, String host, int port, InetAddress localAddress, int localPort, HttpParams params) throws IOException, UnknownHostException, ConnectTimeoutException { int connTimeout = HttpConnectionParams.getConnectionTimeout(params); int soTimeout = HttpConnectionParams.getSoTimeout(params); InetSocketAddress remoteAddress = new InetSocketAddress(host, port); SSLSocket sslsock = (SSLSocket) ((sock != null) ? sock : createSocket()); if ((localAddress != null) || (localPort > 0)) { // we need to bind explicitly if (localPort < 0) { localPort = 0; // indicates "any" } InetSocketAddress isa = new InetSocketAddress(localAddress, localPort); sslsock.bind(isa); } sslsock.connect(remoteAddress, connTimeout); sslsock.setSoTimeout(soTimeout); return sslsock; } /** * @see org.apache.http.conn.scheme.SocketFactory#createSocket() */ public Socket createSocket() throws IOException { return getSSLContext().getSocketFactory().createSocket(); } /** * @see org.apache.http.conn.scheme.SocketFactory#isSecure(java.net.Socket) */ public boolean isSecure(Socket socket) throws IllegalArgumentException { return true; } /** * @see org.apache.http.conn.scheme.LayeredSocketFactory#createSocket(java.net.Socket, java.lang.String, int, * boolean) */ public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException { return getSSLContext().getSocketFactory().createSocket(socket, host, port, autoClose); } // ------------------------------------------------------------------- // javadoc in org.apache.http.conn.scheme.SocketFactory says : // Both Object.equals() and Object.hashCode() must be overridden // for the correct operation of some connection managers // ------------------------------------------------------------------- public boolean equals(Object obj) { return ((obj != null) && obj.getClass().equals(EasySSLSocketFactory.class)); } public int hashCode() { return EasySSLSocketFactory.class.hashCode(); } } 

EasyX509TrustManager:

 public class EasyX509TrustManager implements X509TrustManager { private X509TrustManager standardTrustManager = null; /** * Constructor for EasyX509TrustManager. */ public EasyX509TrustManager(KeyStore keystore) throws NoSuchAlgorithmException, KeyStoreException { super(); TrustManagerFactory factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); factory.init(keystore); TrustManager[] trustmanagers = factory.getTrustManagers(); if (trustmanagers.length == 0) { throw new NoSuchAlgorithmException("no trust manager found"); } this.standardTrustManager = (X509TrustManager) trustmanagers[0]; } /** * @see javax.net.ssl.X509TrustManager#checkClientTrusted(X509Certificate[],String authType) */ public void checkClientTrusted(X509Certificate[] certificates, String authType) throws CertificateException { standardTrustManager.checkClientTrusted(certificates, authType); } /** * @see javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[],String authType) */ public void checkServerTrusted(X509Certificate[] certificates, String authType) throws CertificateException { if ((certificates != null) && (certificates.length == 1)) { certificates[0].checkValidity(); } else { standardTrustManager.checkServerTrusted(certificates, authType); } } /** * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers() */ public X509Certificate[] getAcceptedIssuers() { return this.standardTrustManager.getAcceptedIssuers(); } } 

Y agregué este método: getNewHttpClient ()

 public static 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(); } } 

Finalmente para cada lugar en mi código que tenía:

 DefaultHttpClient client = new DefaultHttpClient(); 

Lo reemplazo por:

 HttpClient client = getNewHttpClient(); 

Aquí está una solución de HttpsUrlConnection POST de Android completa con pinning de certificado, código del lado del servidor de tiempo de espera y configuraciones.

La variable params debe estar en el formulario username = demo & password = abc123 &.

 @Override public String sendHttpRequest(String params) { String result = ""; try { URL url = new URL(AUTHENTICATION_SERVER_ADDRESS); HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); connection.setSSLSocketFactory(KeyPinStore.getInstance().getContext().getSocketFactory()); // Tell the URLConnection to use a SocketFactory from our SSLContext connection.setRequestMethod("POST"); connection.setDoOutput(true); connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); connection.setConnectTimeout(10000); connection.setReadTimeout(10000); PrintWriter out = new PrintWriter(connection.getOutputStream()); out.println(params); out.close(); BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()), 8192); String inputLine; while ((inputLine = in.readLine()) != null) { result = result.concat(inputLine); } in.close(); //} catch (IOException e) { } catch (IOException | KeyStoreException | CertificateException | KeyManagementException | NoSuchAlgorithmException e) { result = e.toString(); e.printStackTrace(); } return result; } 
  • Android L - Sin certificado de igualdad
  • Conexión de socket SSL
  • no se puede conectar al servidor utilizando BKS keystore
  • Android Studio / Intellij, Gradle Error: Causa: no homologado
  • ¿Cómo enviar solicitudes de proxy a api.twitter.com incluyendo certificados SSL?
  • OkHttp certificado de confianza
  • ¿Por qué vuelve Volley a SSLV3?
  • HttpsUrlConnection con proxy
  • Google Cloud Messaging muestra "notRegistered" al usar la aplicación distribuida de iOS
  • Android Google Play Advertencia: Vulnerabilidad de procesador de errores SSL
  • HTTPS GET (SSL) con Android y certificado de servidor auto-firmado
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.