https实现方式分为两种
- 单项认证
- 双向认证
1.安卓端实现:
1.1 单项认证
- Android端通过和服务端发送请求试需要进行认证,认证分为单向认证和双向认证,根据安全性来说还是以双向认证为主。
- 实现单向认证时需要服务端提供一个证书,该证书在服务端生成之后是.cer格式的,我们需要用cmd命令行进行转换成.bks格式的。
- 该证书的作用是在前段向服务端发送请求是以此来限定要被访问的服务端是否安全,是否可信任访问请求数据,只是在前段做认证,通过之后就可访问服务端,而服务端并没有做任何的认证,这也是单向认证的不足之处,安全系数比较低。
- 单向认证的实现代码:生成好的证书需要放到资源文件中。
public static String get(String url) {
try {
DefaultHttpClient httpClient = new MyHttpClient();
HttpGet httpGet = new HttpGet(url);
// HttpClient httpClient = getHttpClient();
HttpResponse httpResponse = httpClient.execute(httpGet);
if(httpResponse.getStatusLine().getStatusCode() == 200){
HttpEntity httpEntity = httpResponse.getEntity();
return EntityUtils.toString(httpEntity);
}
} catch (Exception e) {
LogUtil.e(TAG, e.getMessage());
}
return null;
}
把之前的getHttpClient()注释掉重新创建MyHttpClient(),MyHttpClient()中的代码如下:
public class MyHttpClient extends DefaultHttpClient {
private static Context context;
//此处的PASSWORD为前后端之间的一个密码,唯一标识
private static final String PASSWORD = "123456";
public static void setContext(Context context) {
MyHttpClient.context = context;
}
public MyHttpClient() {
}
public MyHttpClient(HttpParams params) {
super(params);
}
public MyHttpClient(ClientConnectionManager httpConnectionManager, HttpParams params) {
super(httpConnectionManager, params);
}
@Override
protected ClientConnectionManager createClientConnectionManager() {
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
// 用我们自己定义的 SSLSocketFactory 在 ConnectionManager 中注册一个 443 端口
registry.register(new Scheme("https", newSslSocketFactory(), 443));
return new SingleClientConnManager(getParams(), registry);
}
private SSLSocketFactory newSslSocketFactory() {
try {
// 取得BKS密钥库实例
KeyStore trusted = KeyStore.getInstance("BKS");
// 从资源文件中读取你自己创建的那个包含证书的 keystore 文件
// 这个参数改成你的 keystore 文件名
InputStream in = GzApplication.getAppContext().getResources().openRawResource(R.raw.test);
try {
// 用 keystore 的密码跟证书初始化 trusted
trusted.load(in, PASSWORD.toCharArray());
} finally {
in.close();
}
SSLSocketFactory sf = new SSLSocketFactory(trusted);
//允许所有主机的验证
// 这个参数可以根据需要调整, 如果对主机名的验证不需要那么严谨, 可以将这个严谨程度调低些.
sf.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
return sf;
} catch (Exception e) {
throw new AssertionError(e);
}
}
}
1.2 双向认证
双向认证的原理其实和单向大同小异,但是不同是,双向认证需要两个认证证书,也是有服务端提供,格式分别为client.p12和client.truststore,这两个证书也是放到android资源文件下面,以提供在代码中读取。
public static String get(String url) {
try {
HttpGet httpGet = new HttpGet(url);
// HttpClient httpClient = getHttpClient();
HttpResponse httpResponse = httpClient.execute(httpGet);
if(httpResponse.getStatusLine().getStatusCode() == 200){
HttpEntity httpEntity = httpResponse.getEntity();
return EntityUtils.toString(httpEntity);
}
} catch (Exception e) {
LogUtil.e(TAG, e.getMessage());
}
return null;
}
修改getHttpClient()方法中的代码如下:
//https
private static final String KEY_STORE_TYPE_BKS = "bks";
private static final String KEY_STORE_TYPE_P12 = "PKCS12";
private static final String SCHEME_HTTPS = "https";
private static final int HTTPS_PORT = 443;
private static final String KEY_STORE_CLIENT_PATH = "client.p12";
private static final String KEY_STORE_TRUST_PATH = "client.truststore";
private static final String KEY_STORE_PASSWORD = "123456";
private static final String KEY_STORE_TRUST_PASSWORD = "123456";
private static KeyStore keyStore;
private static KeyStore trustStore;
public static HttpClient getHttpClient() {
HttpClient httpsClient = new DefaultHttpClient();
try {
// 服务器端需要验证的客户端证书
keyStore = KeyStore.getInstance(KEY_STORE_TYPE_P12);
// 客户端信任的服务器端证书
trustStore = KeyStore.getInstance(KEY_STORE_TYPE_BKS);
// 从资源文件中读取你自己创建的那个包含证书的 keystore 文件
// 这个参数改成你的 keystore 文件名
InputStream ksIn = GzApplication.getAppContext().getResources().getAssets().open(KEY_STORE_CLIENT_PATH);
InputStream tsIn = GzApplication.getAppContext().getResources().getAssets().open(KEY_STORE_TRUST_PATH);
try {
keyStore.load(ksIn, KEY_STORE_PASSWORD.toCharArray());
trustStore.load(tsIn, KEY_STORE_TRUST_PASSWORD.toCharArray());
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
ksIn.close();
} catch (Exception ignore) {
}
try {
tsIn.close();
} catch (Exception ignore) {
}
}
SSLSocketFactory socketFactory = new SSLSocketFactory(keyStore, KEY_STORE_PASSWORD, trustStore);
Scheme sch = new Scheme(SCHEME_HTTPS, socketFactory, HTTPS_PORT);
httpsClient.getConnectionManager().getSchemeRegistry().register(sch);
} catch (KeyManagementException e) {
e.printStackTrace();
} catch (UnrecoverableKeyException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}