tôi có phương pháp này:Thay đổi HTTP bài yêu cầu HTTPS bài yêu cầu:
public static String getReportMetadata (String reportId, String sessionId, String url) throws Exception{
Map<String, Object> jsonValues = new HashMap<String, Object>();
jsonValues.put("reportID", reportId);
jsonValues.put("sessionID", sessionId);
JSONObject json = new JSONObject(jsonValues);
DefaultHttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(url + GET_REPORT_METADATA_ACTION);
AbstractHttpEntity entity = new ByteArrayEntity(json.toString().getBytes("UTF8"));
entity.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
post.setEntity(entity);
HttpResponse response = client.execute(post);
return getContent(response);
}
rằng thực hiện một bài yêu cầu HTTP
mà of-Tất nhiên tôi chạy bằng AsyncTask
để lấy dữ liệu từ máy chủ.
Câu hỏi của tôi: có thể một số một xin vui lòng giải thích cho tôi một cách đơn giản các bước tôi cần phải thực hiện để thay đổi loại kết nối này cho một kết nối an toàn (còn được gọi bằng HTTPS
) là gì. Chỉ từ quan điểm android (nghĩa là ứng dụng khách).
CẬP NHẬT: Như đã đề xuất, tôi đã cố gắng chỉ thay đổi liên kết và thêm https thay vì http nhưng không trả lại câu trả lời. Như tôi hiểu rằng tôi không cần phải nhận được và lưu trữ một chứng chỉ tự đăng nhập để kết nối với phía máy chủ
UPDATE2: Các giải pháp mà làm việc cho tôi:
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();
}
}
Và tôi đã thêm phương pháp này: 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();
}
}
Cuối cùng cho mọi nơi trong mã của tôi rằng tôi đã có:
DefaultHttpClient client = new DefaultHttpClient();
tôi thay thế nó bằng:
HttpClient client = getNewHttpClient();
Tôi hiện có thể nhận dữ liệu từ phía máy chủ, câu hỏi cuối cùng là: là những gì tôi đã làm là an toàn không? hoặc nó chấp nhận từng chứng chỉ tự ký? nếu đây là trường hợp cần phải làm gì để thay đổi nó?
Mọi trợ giúp sẽ được đánh giá cao.
Có lẽ javadoc sẽ giúp bạn: [SchemeRegistry] (http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/conn/scheme/SchemeRegistry.html) [SSLSocketFactory] (http: //hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/conn/ssl/SSLSocketFactory.html) – mleczey
Theo [Hướng dẫn SSL HTTPClient] (htt p: //hc.apache.org/httpclient-legacy/sslguide.html), thực sự điều duy nhất bạn cần làm là đặt "https: //" vào chuỗi URL của bạn. Điều này sẽ cung cấp cho bạn kết nối HTTPS với cấp xác thực tương đương với trình duyệt (nghĩa là bất kỳ một trong số hàng trăm CA nào cũng có thể ký chứng chỉ máy chủ). Các 'SchemeRegistry' và' SSLSocketFactory' chỉ đi vào chơi nếu bạn muốn tùy chỉnh xử lý SSL, thường là để thực hiện SSL pinning (có nghĩa là, sử dụng một ràng buộc xác thực mạnh mẽ hơn). Hãy xem github của Moxie để có được một bộ pin ssl Android (LGPL được cấp phép). – Barend
@Bây giờ, tôi đã cố gắng chỉ thay đổi liên kết và thêm https thay vì http nhưng không trả lại câu trả lời. Theo tôi hiểu tôi cần phải nhận và lưu trữ chứng chỉ tự ký để kết nối với phía máy chủ. –