Как сделать HTTPS POST с Android?
Я хочу, чтобы метод отправки HTTPS отправлял некоторые данные из моего приложения Android на мой сайт.
HttpURLConnection
я использовал HttpURLConnection
и он отлично работает с моим HTTP-адресом. Мой веб-сайт работает на HTTPS, и я хочу отправить тот же POST с помощью HttpsURLConnection
. Может ли кто-нибудь помочь мне правильно использовать class?
Я нашел источник по этой ссылке :
- java, расширяющий class с конструктором основного classа имеет параметр
- Библиотека PDF для рендеринга файлов PDF в Android
- Как анализировать дату с GMT TimeZone на IST TimeZone и наоборот в android
- Android Horizontal LinearLayout - Элементы обертки
- Android Context.bindService всегда возвращает false, а объект ServiceConnection никогда не запускается
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();
Какова должна быть ценность KeyStore keyStore = ...;
?
Я попытался отправить данные, используя тот же HttpURLConnection
, но я вижу, что некоторые POST-данные пропущены или ошибочны.
Я пробовал метод из этого вопроса . Я вставляю свой код ниже
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; }
Ошибка, которую я получаю, ниже:
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)
- В чем разница между List и ArrayList?
- Есть ли у java int.tryparse, который не генерирует исключение для плохих данных?
- Android Studio: не удалось выполнить выполнение gradleиента, причина пуста
- Как проверить имя сертификата и псевдоним в файлах хранилища ключей?
- Как избежать избыточности кода конструктора в Java?
- Gradle - Что такое ненулевое значение выхода и как его исправить?
- Как Facebook добавляет номера значков на значок приложения в Android?
- Android: прослушиватель изменений в подключении к Интернету
Вы можете использовать CA по умолчанию, которые определены в устройстве Android, что отлично подходит для любой общедоступной сети.
Если у вас есть самозаверяющий сертификат, вы можете принять все сертификаты (рискованные, открытые для атак типа «человек-в-середине») или создать собственный TrustManagerFactory
, который немного отличается от этой области.
Вот код для использования ЦС по умолчанию для вызова https POST:
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(); }
Чтобы прочитать ответ:
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; }
Вы можете взглянуть на этот вопрос, который я задал несколько дней назад:
Измените HTTP-запрос на отправку запроса HTTPS:
Я поставил там решение, которое сработало для меня, что в принципе принимает любой самоподписанный сертификат. Как было сказано здесь, это решение не рекомендуется, так как оно не безопасно и открыто для нападений «человек в середине».
Вот код:
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(); } }
И я добавил этот метод: 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(); } }
Наконец, для каждого места в моем коде, которое у меня было:
DefaultHttpClient client = new DefaultHttpClient();
Я заменяю его:
HttpClient client = getNewHttpClient();
Вот приложение Android HttpsUrlConnection POST с сертификатом, тайм- аутом и кодом сервера.
Параметр переменной должен быть в форме 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; }