Tôi muốn tạo một Ứng dụng kết nối với máy chủ. Máy chủ này sử dụng Xác thực ứng dụng khách SSL. Người dùng ứng dụng sẽ có thể chọn chứng chỉ và cho phép sử dụng chứng chỉ như được triển khai trong ứng dụng trình duyệt.Xác thực ứng dụng khách SSL trong Android 4.x
Trong ứng dụng trình duyệt, xác thực đang hoạt động như mong đợi, vì vậy chứng chỉ tôi sử dụng hợp lệ.
Khi tôi cố gắng kết nối trong App của tôi tôi nhận được lỗi sau:
javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException:
SSL handshake terminated: ssl=0x2a2d3b38:
Failure in SSL library, usually a protocol error
error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure
(external/openssl/ssl/s3_pkt.c:1290 0x2a2df880:0x00000003)
Tôi cố gắng để làm theo các tài liệu android cho việc thực hiện của tôi.
Đây là mã của Hoạt động mẫu của tôi:
public class ClientCertificateActivity extends Activity implements
KeyChainAliasCallback {
protected static final String TAG = "CERT_TEST";
private String alias;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
choseCertificate();
LinearLayout layout = new LinearLayout(this);
Button connectToServer = new Button(this);
connectToServer.setText("Try to connect to Server");
connectToServer.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
connectToServer.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
connectToServer();
}
});
layout.addView(connectToServer);
addContentView(layout, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
}
protected void connectToServer() {
final Context ctx = this;
new AsyncTask<Void, Void, Boolean>() {
private Exception error;
@Override
protected Boolean doInBackground(Void... arg) {
try {
PrivateKey pk = KeyChain.getPrivateKey(ctx, alias);
X509Certificate[] chain = KeyChain.getCertificateChain(ctx,
alias);
KeyStore keyStore = KeyStore.getInstance("AndroidCAStore");
TrustManagerFactory tmf = TrustManagerFactory
.getInstance(TrustManagerFactory
.getDefaultAlgorithm());
tmf.init(keyStore);
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
URL url = new URL("https://usecert.example.com/");
HttpsURLConnection urlConnection = (HttpsURLConnection) url
.openConnection();
urlConnection.setSSLSocketFactory(context
.getSocketFactory());
InputStream in = urlConnection.getInputStream();
return true;
} catch (Exception e) {
e.printStackTrace();
error = e;
return false;
}
}
@Override
protected void onPostExecute(Boolean valid) {
if (error != null) {
Toast.makeText(ctx, "Error: " + error.getMessage(),
Toast.LENGTH_LONG).show();
return;
}
Toast.makeText(ctx, "Success: ", Toast.LENGTH_SHORT).show();
}
}.execute();
}
protected void choseCertificate() {
KeyChain.choosePrivateKeyAlias(this, this,
new String[] { "RSA", "DSA" }, null, "m.ergon.ch", 443, null);
}
@Override
public void alias(String alias) {
this.alias = alias;
}
}
Các ngoại lệ được ném vào urlConnection.getInputStream();
Đây là việc bắt giữ những cái bắt tay giữa máy chủ và c lient.
Cảm ơn mọi lời đề nghị và lời nhắn.
Cảm ơn điều đó. Nhưng làm cách nào tôi có thể tạo KeyManager như vậy bằng khóa riêng của mình? Phần này bị thiếu trong ví dụ tại [Android Doc cho HttpsURLConnection] (http://developer.android.com/reference/javax/net/ssl/HttpsURLConnection.html) – surffan
Có vẻ như không phải là cách trực tiếp để làm điều này. Bạn sẽ phải thực hiện 'X509KeyManager' để trả về' PrivateKey' và một số bí danh mã hóa cứng. Bạn không cần phải triển khai các phương thức liên quan đến máy chủ. http://developer.android.com/reference/javax/net/ssl/X509KeyManager.html –
Xem câu trả lời cập nhật cho mã mẫu. –