【android安全】之使用ssl驗證保護網路資料傳輸安全。
阿新 • • 發佈:2019-01-01
package com.test; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URL; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.UUID; import javax.net.ssl.HttpsURLConnection; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.HttpVersion; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.conn.scheme.PlainSocketFactory; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.scheme.SchemeRegistry; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; import org.apache.http.message.BasicNameValuePair; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; import org.apache.http.params.HttpProtocolParams; import org.apache.http.protocol.HTTP; import org.apache.http.util.EntityUtils; import org.thoughtcrime.ssl.pinning.PinningSSLSocketFactory; import org.thoughtcrime.ssl.pinning.util.PinningHelper; import android.content.Context; public class SSLHttpUtil { private final static int CONNET_TIMEOUT = 10 * 1000; private final static int READ_TIMEOUT = 10 * 1000; private final static String ENCODING = "GBK"; /** * * @param urlString * @param params * @param files * @param pins * 伺服器各個證書的pin碼集合。 * @param context * @return */ public static String post(String urlString, Map<String, String> params, Map<String, File> files, String[] pins, Context context) { HttpsURLConnection conn = null; DataOutputStream outStream = null; try { String BOUNDARY = UUID.randomUUID().toString(); String PREFIX = "--", LINEND = "\r\n"; String MULTIPART_FROM_DATA = "multipart/form-data"; URL url = new URL(urlString); conn = PinningHelper .getPinnedHttpsURLConnection(context, pins, url); conn.setReadTimeout(READ_TIMEOUT); conn.setConnectTimeout(CONNET_TIMEOUT); conn.setDoInput(true); conn.setDoOutput(true); conn.setUseCaches(false); conn.setRequestMethod("POST"); conn.setRequestProperty("connection", "keep-alive"); conn.setRequestProperty("Charsert", "UTF-8"); conn.setRequestProperty("Content-Type", MULTIPART_FROM_DATA + ";boundary=" + BOUNDARY); // outStream = new DataOutputStream(conn.getOutputStream()); if (params != null) { // 棣栧厛緇勬嫾鏂囨湰綾誨瀷鐨勫弬錕�? StringBuilder sb = new StringBuilder(); for (Map.Entry<String, String> entry : params.entrySet()) { sb.append(PREFIX); sb.append(BOUNDARY); sb.append(LINEND); sb.append("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"" + LINEND); sb.append("Content-Type: text/plain; charset=" + ENCODING + LINEND); sb.append("Content-Transfer-Encoding: 8bit" + LINEND); sb.append(LINEND); sb.append(entry.getValue()); sb.append(LINEND); } outStream.write(sb.toString().getBytes()); } // 鍙戱拷?錕芥枃浠舵暟錕�? if (files != null) { for (Map.Entry<String, File> file : files.entrySet()) { StringBuilder sb1 = new StringBuilder(); sb1.append(PREFIX); sb1.append(BOUNDARY); sb1.append(LINEND); sb1.append("Content-Disposition: form-data; name=\"" + file.getKey() + "\"; filename=\"" + file.getValue().getName() + "\"" + LINEND); sb1.append("Content-Type: application/octet-stream; charset=" + ENCODING + LINEND); sb1.append(LINEND); outStream.write(sb1.toString().getBytes()); InputStream is = new FileInputStream(file.getValue()); byte[] buffer = new byte[1024]; int len = 0; while ((len = is.read(buffer)) != -1) { outStream.write(buffer, 0, len); } is.close(); outStream.write(LINEND.getBytes()); } } // 璇鋒眰緇撴潫鏍囧織 byte[] end_data = (PREFIX + BOUNDARY + PREFIX + LINEND).getBytes(); outStream.write(end_data); outStream.flush(); String sb2 = null; if (conn.getResponseCode() == HttpStatus.SC_OK) { InputStream in = conn.getInputStream(); sb2 = readStreamToString(in); } return sb2; } catch (Exception e) { e.printStackTrace(); return null; } finally { try { outStream.close(); conn.disconnect(); } catch (Exception e) { // ignore. e.printStackTrace(); } } } private static String readStreamToString(InputStream inStream) { ByteArrayOutputStream outStream = null; try { outStream = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len = 0; while ((len = inStream.read(buffer)) != -1) { outStream.write(buffer, 0, len); } inStream.close(); outStream.flush(); String ret = outStream.toString(); outStream.close(); return ret; } catch (Exception e) { try { inStream.close(); outStream.close(); } catch (Exception e1) { // TODO Auto-generated catch block e1.printStackTrace(); } return null; } } /** * * @param url * @param params * @param context * @param pins * 伺服器各個證書的pin碼集合。 * @return */ public static String get(String url, Map<String, String> params, Context context, String[] pins) { try { String realUrl = generateUrl(url, params); HttpClient client = getNewHttpClient(context, pins); HttpGet getMethod = new HttpGet(realUrl); HttpResponse response = client.execute(getMethod); if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { StringBuilder builder = new StringBuilder(); BufferedReader reader = new BufferedReader( new InputStreamReader(response.getEntity().getContent())); for (String s = reader.readLine(); s != null; s = reader .readLine()) { builder.append(s); } String result = builder.toString(); return result; } } catch (Exception e) { e.printStackTrace(); } return null; } /** * * @param url * @param params * @param context * @param pins * 伺服器各個證書的pin碼集合。 * @return */ public static String post(String url, Map<String, String> params, Context context, String[] pins) { try { HttpClient client = getNewHttpClient(context, pins); HttpPost postMethod = new HttpPost(url); List<BasicNameValuePair> pairs = new ArrayList<BasicNameValuePair>(); if (params != null && params.size() > 0) { Iterator<Entry<String, String>> iterator = params.entrySet() .iterator(); while (iterator.hasNext()) { Entry<String, String> param = iterator.next(); String key = param.getKey(); String value = param.getValue(); BasicNameValuePair pair = new BasicNameValuePair(key, value); pairs.add(pair); } postMethod .setEntity(new UrlEncodedFormEntity(pairs, HTTP.UTF_8)); } HttpResponse response = client.execute(postMethod); if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { return EntityUtils.toString(response.getEntity()); } } catch (Exception e) { e.printStackTrace(); } return null; } /** * 鑾峰彇HttpClient * * @return */ private static HttpClient getNewHttpClient(Context context, String[] pins) { try { HttpParams params = new BasicHttpParams(); HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); HttpProtocolParams.setContentCharset(params, HTTP.UTF_8); HttpConnectionParams.setConnectionTimeout(params, CONNET_TIMEOUT); HttpConnectionParams.setSoTimeout(params, READ_TIMEOUT); SchemeRegistry registry = new SchemeRegistry(); registry.register(new Scheme("http", PlainSocketFactory .getSocketFactory(), 80)); registry.register(new Scheme("https", new PinningSSLSocketFactory( context, pins, 0), 443)); ClientConnectionManager ccm = new ThreadSafeClientConnManager( params, registry); return new DefaultHttpClient(ccm, params); } catch (Exception e) { return new DefaultHttpClient(); } } private static String generateUrl(String url, Map<String, String> params) { StringBuilder urlBuilder = new StringBuilder(url); if (null != params) { urlBuilder.append("?"); Iterator<Entry<String, String>> iterator = params.entrySet() .iterator(); while (iterator.hasNext()) { Entry<String, String> param = iterator.next(); String key = param.getKey(); String value = param.getValue(); urlBuilder.append(key).append('=').append(value); if (iterator.hasNext()) { urlBuilder.append('&'); } } } return urlBuilder.toString(); } }
備註:獲取伺服器證書pin碼的方法: