#java #android #ssl #client
#java #Android #ssl #клиент
Вопрос:
Я пытался заставить клиента безопасно взаимодействовать с сервером через SSL. Я создал свои собственные самозаверяющие сертификаты, и кажется, что клиент может подключиться к серверу, используя сертификаты, но клиент, похоже, никогда не получает ответа от сервера. Я попытался напечатать content-length, который возвращает -1, и фактическое содержимое кажется пустой строкой, хотя ожидается простой HTML ‘hello world’.
Что я делаю не так?
Сервер:
public class SSLServer {
public static void main(String[] args) {
String ksName = "key.jks";
char ksPass[] = "password".toCharArray();
char ctPass[] = "password".toCharArray();
try {
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream(ksName), ksPass);
KeyManagerFactory kmf =
KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, ctPass);
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(kmf.getKeyManagers(), null, null);
SSLServerSocketFactory ssf = sc.getServerSocketFactory();
SSLServerSocket s
= (SSLServerSocket) ssf.createServerSocket(8888);
System.out.println("Server started:");
// Listening to the port
SSLSocket c = (SSLSocket) s.accept();
BufferedWriter w = new BufferedWriter(
new OutputStreamWriter(c.getOutputStream()));
w.write("HTTP/1.0 200 OK");
w.write("Content-Type: text/html");
w.write("<html><body>Hello world!</body></html>");
w.flush();
w.close();
c.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Клиент:
public class TestSSLActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Instantiate the custom HttpClient
DefaultHttpClient client = new MyHttpClient(getApplicationContext());
HttpGet get = new HttpGet("https://192.168.15.195:8888");
// Execute the GET call and obtain the response
HttpResponse getResponse;
try {
getResponse = client.execute(get);
HttpEntity responseEntity = getResponse.getEntity();
Log.i("Connection",responseEntity.getContentLength() "");
BufferedReader reader = new BufferedReader(new InputStreamReader(responseEntity.getContent(), "UTF-8"));
StringBuilder builder = new StringBuilder();
for (String line = null; (line = reader.readLine()) != null;) {
builder.append(line).append("n");
}
Log.i("Connection","build: " builder.toString());
} catch (Exception e) {
Log.i("Connection",e.getMessage());
}
}
Пользовательский HTTP-клиент:
public class MyHttpClient extends DefaultHttpClient {
final Context context;
public MyHttpClient(Context context) {
this.context = context;
}
@Override
protected ClientConnectionManager createClientConnectionManager() {
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
// Register for port 443 our SSLSocketFactory with our keystore
// to the ConnectionManager
registry.register(new Scheme("https", newSslSocketFactory(), 443));
return new SingleClientConnManager(getParams(), registry);
}
private SSLSocketFactory newSslSocketFactory() {
try {
// Get an instance of the Bouncy Castle KeyStore format
KeyStore trusted = KeyStore.getInstance("BKS");
// Get the raw resource, which contains the keystore with
// your trusted certificates (root and any intermediate certs)
InputStream in = context.getResources().openRawResource(R.raw.key);
try {
// Initialize the keystore with the provided trusted certificates
// Also provide the password of the keystore
trusted.load(in, "password".toCharArray());
} finally {
in.close();
}
// Pass the keystore to the SSLSocketFactory. The factory is responsible
// for the verification of the server certificate.
SSLSocketFactory sf = new SSLSocketFactory(trusted);
// Hostname verification from certificate
// http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e506
sf.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
return sf;
} catch (Exception e) {
throw new AssertionError(e);
}
}
}
Ответ №1:
Возможно, вы захотите изменить код сервера, чтобы прочитать запрос от клиента перед отправкой ответа. Может быть, клиент блокирует (а затем истекает время ожидания?) ожидание, пока сервер прочитает запрос.