2013-05-12 15 views
13

Chcę zrobić metodę postów HTTPS, aby wysłać niektóre dane z mojej aplikacji na Androida do mojej witryny.Jak wykonać test HTTPS POST z Androida?

Najpierw użyłem HttpURLConnection i działa dobrze z moim adresem URL HTTP. Moja witryna produkcyjna działa na HTTPS i chcę wysłać ten sam POST za pomocą HttpsURLConnection. Czy ktoś może mi pomóc prawidłowo korzystać z klasy?

znalazłem jakieś źródło na this link:

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

jaka powinna być wartość KeyStore keyStore = ...;?

Próbowałem wysłać dane przy użyciu tego samego HttpURLConnection, ale widzę, że niektóre dane POST zostały pominięte lub pomyłkowo.

Próbowałem tej metody od this question. Ja wklejenie mojego kodu poniżej

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

błąd pojawia otrzymuję jest poniżej:

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) 
+0

zakładowy log a błąd widać – tbkn23

+0

z powyższego przykładowego kodu z Google, nie wiem, co umieścić na kluczy kluczy = ...; – Dino

+0

httpRequest IOException: java.io.FileNotFoundException: ten błąd występuje w przypadku niektórych metod POST, używam HttpURLConnection z https URL – Dino

Odpowiedz

17

Można użyć CAS domyślne, które są zdefiniowane w urządzeniu android, który jest po prostu w porządku dla każdej publicznej sieci .

Jeśli masz samopodpisany certyfikat, możesz zaakceptować wszystkie certyfikaty (ryzykowne, otwarte na ataki typu "w środku") lub utworzyć własny TrustManagerFactory, który jest nieco poza tym zakresem.

Oto niektóre kodu, aby użyć domyślnego CAS połączenia https postu:

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

Aby odczytać odpowiedź:

 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;    
     }  
+0

Wyjątek IOException: java.io.IOException: nieoczekiwany koniec strumienia komunikat nadchodzi – Dino

+0

InputStream inStream = conn.getInputStream(); response = inStream.toString(); – Dino

+0

Nigdy nie próbowałem odczytywać 'InputStream' z' toString() '... Dodano kod, którego używam do odczytu strumienia – tbkn23

4

Można spojrzeć na to pytanie zadałem kilka dni temu:

Change HTTP post request to HTTPS post request:

mam dostarczany istnieje rozwiązanie t kapelusz pracował dla mnie, który zasadniczo akceptuje każdy samopodpisany certyfikat. Jak już powiedziano, to rozwiązanie nie jest zalecane, ponieważ nie jest bezpieczne i otwarte na ataki typu "man-in-the-middle".

tutaj kod:

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

I dodaje się tę metodę: 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(); 
    } 
} 

końcu do każdego miejsca w moim kodu, który miałem:

DefaultHttpClient client = new DefaultHttpClient(); 

zastąpić go z:

HttpClient client = getNewHttpClient(); 
+0

HttpClient jest przestarzałe –

+0

MySSLSocketFactory? – Shankar

3

Oto Android HttpsUrlConnection POST solution wraz z certyfikatem pinningu, limity czasu serwera kod boczną oraz konfiguracje .

Zmienna params powinna mieć postać nazwa użytkownika = demo & hasło = 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; 
} 
+0

Bardzo dobrze. Działa na moim Lollipop 5.0. Dzięki. Co to jest KeyPinStore? – ashishdhiman2007

Powiązane problemy