HttpsURLConnection на localhost


    Для отладки программ, работающих с протоколом HTTPS на локальном компьютере представлен следующий пример.

    Для начала необходимо установить сервер Apache. Настроить его для работы с протоколом https. Информацию, как устанавливать Apache, можно найти в интернете.

    Разместить на этом сервере сценарий для проверки. Например, можно взять простой сценарий на языке Си:

// script.c file
#include <stdio.h>
#include <stdlib.h>

int main(void) {
     char *remote_addr = getenv("REMOTE_ADDR");
     char *content_length = getenv("CONTENT_LENGTH");
     int num_bytes = atoi(content_length);
     char *data = (char *)malloc(num_bytes + 1);
     fread(data, 1, num_bytes, stdin);
     data[num_bytes] = 0;
     printf("Content-type: text/html\n\n");
     printf("Hello. We know about you all!\n");
     printf("Your IP-address: %s\n", remote_addr);
     printf("Count of data bytes: %d\n", num_bytes);
     printf("There are parameters you have entered:\n%s", data);
     return 0;
}

    Скомпилировать его на любом компиляторе (VC, MinGW и т. д.). Переименовать расширение exe на cgi и разместить в папке cgi локального хоста сервера. У меня получился файл script.cgi.

    Далее создаем приложение Android в Eclipse. В файле AndroidMainifest.xml разрешаем доступ в интернет:

    <uses-permission android:name="android.permission.INTERNET" ></uses-permission>


    Код файла Activity:


import java.io.IOException;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.GeneralSecurityException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Scanner;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

public class MainActivity extends Activity {
	
	private TextView tv;
	private static SSLSocketFactory socketFactory;
	private static final HostnameVerifier verifier;
	
	static {
		//Для допуска любого сертификата создаем базовый TrustManager
		final TrustManager[] tm = new TrustManager[] { 
			new X509TrustManager() {
				@Override
				public void checkClientTrusted(X509Certificate[] chain,
					String authType) throws CertificateException {
				}

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

				@Override
				public X509Certificate[] getAcceptedIssuers() {
					return null;
				}
		} };
		
		//Для допуска любого имени хоста создаем базовый HostnameVerifier
		verifier = new HostnameVerifier() {
			@Override
			public boolean verify(String arg0, SSLSession arg1) {
				
				return true;
			}
		};
		
		try {
			//В Android используется криптографический протокол TLS аналог SSLv3
			
			SSLContext sc = SSLContext.getInstance("TLS");
			
			sc.init(null, tm, null);
			
			socketFactory = sc.getSocketFactory();
		} catch (GeneralSecurityException e) {
    		Log.v("GeneralSecurityException", e.toString());
    	}
	}

    @Override
    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        tv = (TextView)findViewById(R.id.text);
	//Обращение эмулятора к локальному хосту 127.0.0.1
	//проводится через ip-адрес 10.0.2.2
        String srv = "https://10.0.2.2/cgi-bin/script.cgi"; 
        
        connectToServer(srv);
    }
    
    private void connectToServer(String srv) {
    	URL url;
    	HttpsURLConnection conn;  
    	
    	try {
    		url = new URL(srv);
    		String param = "param1=" + URLEncoder.encode("value 1", "UTF-8") +
					"&param2=" + URLEncoder.encode("value2", "UTF-8") +
					"&param3=" + URLEncoder.encode("value3", "UTF-8") ;
					
    		//Соединение не всегда удается с первого раза,
			//поэтому даем разрешение на вторую попытку
			int counter = 0;
			while(true)
			{
				HttpsURLConnection.setDefaultHostnameVerifier( verifier);
				conn = (HttpsURLConnection)url.openConnection();
				
				HttpsURLConnection.setDefaultSSLSocketFactory(socketFactory);
				conn.setDoOutput(true);
				conn.setDoInput(true);
				conn.setRequestMethod("POST"); 
				conn.addRequestProperty("Content-Type", 
					"application/xml; charset=utf-8");
				
				//Попытка соединения с сервером
				try {
					conn.connect();
					break;
				} catch(IOException ex){
					counter++;
					
					conn.disconnect();
					conn = null;
					if (counter == 2)
						break;
					else
						continue;
				}
			}
			if (conn == null) return;

			//Передаем запрос с параметрами на сервер
			PrintWriter out = new PrintWriter(conn.getOutputStream());
			
			out.print(param); 
			
			out.close();
			
			//Получаем ответ с сервера
			
			Scanner scanner = new Scanner(conn.getInputStream()); 
			StringBuilder sb = new StringBuilder();
			while(scanner.hasNextLine())
				sb.append(URLDecoder.decode(scanner.nextLine(), "UTF-8") + "\n");
			scanner.close();

			//Отображаем ответ на дисплее				
			tv.setText(sb.toString());
			
			//Отсоединяемся от сервера
			conn.disconnect();
			
    		
    	} catch(IOException ex){
    		Log.v("IOException", ex.toString());
    		
    	}
    }
}


    Запускаем программу и получаем:




    Автор статьи: Дмитрий Изергин