How to do an HTTPS POST from Android?

后端 未结 3 1034
日久生厌
日久生厌 2020-11-29 04:07

I want to do a HTTPS post method to send some data from my android app to my website.

I used HttpURLConnection first and it\'s working fine with my HTT

相关标签:
3条回答
  • 2020-11-29 04:34

    You can use the default CAs that are defined in the android device, which is just fine for any public web.

    If you have a self-signed certificate, you can either accept all certificates (risky, open to man-in-the-middle attacks) or create your own TrustManagerFactory, which is a bit out of this scope.

    Here's some code to use the default CAs for a https POST call:

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

    To read the response:

    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 讨论(0)
  • 2020-11-29 04:38

    Here's an Android HttpsUrlConnection POST solution complete with certificate pinning, timeouts server side code and configurations.

    The variable params should be in the form 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;
    }
    
    0 讨论(0)
  • 2020-11-29 04:47

    You can take a look at this question I asked a few days ago:

    Change HTTP post request to HTTPS post request:

    I have supplied there a solution that worked for me, that basically accepts any self-signed certificate. As been said here this solution is not recommended as it's not secure and open to a man-in-the-middle attacks.

    Here is the code:

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

    And I added this method: 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();
        }
    }
    

    Finally for every place in my code that I had:

    DefaultHttpClient client = new DefaultHttpClient();
    

    I replace it with:

    HttpClient client = getNewHttpClient();
    
    0 讨论(0)
提交回复
热议问题