使用自定义证书并忽略验证的HTTPS连接Post请求方式的封装
-
使用自定义证书并忽略验证的HTTPS连接方式
-
解决证书不被系统承认的方法,就是跳过系统校验。要跳过系统校验,就不能再使用系统标准的SSL SocketFactory了,需要自定义一个。
-
然后为了在这个自定义SSL SocketFactory里跳过校验,还需要自定义一个TrustManager,在其中忽略所有校验,即TrustAll。
HttpClientInstance:
public class HttpClientInstance {
private static HttpClient mHttpClient = null;
public static synchronized HttpClient getHttpsClientIns() {
if (mHttpClient == null) {
try {
KeyStore trustStore = KeyStore.getInstance(KeyStore
.getDefaultType());
trustStore.load(null, null);
SSLSocketFactory sf = new SSLSocketFactoryImp(trustStore);
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
HttpParams httpParameters = new BasicHttpParams();
HttpConnectionParams
.setConnectionTimeout(httpParameters, 20000);
HttpConnectionParams.setSoTimeout(httpParameters, 20000);
HttpProtocolParams.setVersion(httpParameters,
HttpVersion.HTTP_1_1);
HttpProtocolParams
.setContentCharset(httpParameters, 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(
httpParameters, registry);
mHttpClient = new DefaultHttpClient(ccm, httpParameters);
return mHttpClient;
} catch (Exception e) {
e.printStackTrace();
}
}
return mHttpClient;
}
public static class SSLSocketFactoryImp extends SSLSocketFactory {
final SSLContext sslContext = SSLContext.getInstance("TLS");
public SSLSocketFactoryImp(KeyStore truststore)
throws NoSuchAlgorithmException, KeyManagementException,
KeyStoreException, UnrecoverableKeyException {
super(truststore);
TrustManager tm = new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkClientTrusted(
java.security.cert.X509Certificate[] chain,
String authType)
throws java.security.cert.CertificateException {
}
@Override
public void checkServerTrusted(
java.security.cert.X509Certificate[] chain,
String authType)
throws java.security.cert.CertificateException {
}
};
sslContext.init(null, new TrustManager[] { tm }, null);
}
@Override
public Socket createSocket(Socket socket, String host, int port,
boolean autoClose) throws IOException, UnknownHostException {
return sslContext.getSocketFactory().createSocket(socket, host,
port, autoClose);
}
@Override
public Socket createSocket() throws IOException {
return sslContext.getSocketFactory().createSocket();
}
}
}
HttpRequestDispatch:
这个类作为网络连接的封装类,继承Thread,构造函数有5个参数,分别为所在类,Handler,URL,post请求参数,以及handler的索引值。
public class HttpRequestDispatch extends Thread
{
private BaseAction mAction = null;
private Handler mHandler = null;
private String mUrl = null;
private List<NameValuePair> mParams = null;
private int mHandlerIndex = 0;
public HttpRequestDispatch(BaseAction action,Handler handler,String url,List<NameValuePair> params,int handlerIndex)
{
mAction = action;
mHandler = handler;
mUrl = url;
mParams = params;
mHandlerIndex = handlerIndex;
}
public void run()
{
try
{
if(mUrl == null || mHandler == null)
{
mAction.alertToast("请求地址不能为空");
return;
}
HttpClient httpsClient = HttpClientInstance.getHttpsClientIns();
HttpPost httpRequest = new HttpPost(mUrl);
if(mParams != null)
{
httpRequest.setEntity(new UrlEncodedFormEntity(mParams,HTTP.UTF_8));
}
HttpResponse response = httpsClient.execute(httpRequest);
if(response.getStatusLine().getStatusCode() != HttpURLConnection.HTTP_OK)
{
throw new Exception("ResponseCode:" + response.getStatusLine().getStatusCode());
}
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer buffer = new StringBuffer();
String line = null;
while ((line = reader.readLine()) != null)
{
buffer.append(line);
}
sendResultBack(buffer.toString());
}
catch(Exception e)
{
Message message = mHandler.obtainMessage();
message.what = HttpTool.HTTP_DISPATH_ERROR;
message.obj = e.getMessage();
mHandler.sendMessage(message);
e.printStackTrace();
}
}
private void sendResultBack(String result)
{
Message message = mHandler.obtainMessage();
message.what = mHandlerIndex;
message.obj = result;
mHandler.sendMessage(message);
}
}
这样所有的后台交互的封装已经差不多了,也可以根据以上修改下,因为不只是使用自定义证书忽略,也可是系统,也可以验证自定义证书,依情况而定。
接下来看下如何调用的,只需要在交互的方法中去New一个HttpRequestDispatch,拿登陆来说,
LoginAction:
private void processUserLogin(String phone, String pass, String code) {
List<NameValuePair> params = new ArrayList<NameValuePair>();
JSONObject json = new JSONObject();
try {
json.put("username", phone);
json.put("password",pass);
} catch (JSONException e) {
e.printStackTrace();
}
params.add(new BasicNameValuePair("message", MyUtils
.encodeBase64String(json.toString())));
new HttpRequestDispatch(LoginAction.this, mHandler,
HttpUrl.getLoginUrl(), params, STATE_LOGIN_INFO).start();
}
虽然说现在不少网络交互的框架应有尽有,Volly,Okhttp,再到现在的Retrofit+RxJava等,但并不能代表源生的有多么差,看个人爱好吧。