Android为我们提供了两种HTTP交互的方式: HttpURLConnection 和 Apache HTTP Client
当访问https时,认证方案在客户端可以决定是否验证服务器,而服务器端可以选择是否验证客户端,如果双方都选择验证那么,就是双向验证;如果有一方选择不验证,那就是单向验证。
双向认证:服务器验证客户端,需要给手机安装证书(参考http://blog.csdn.net/yuxiaohui78/article/details/41975915)
单向认证: 即不验证服务器,在连接过程中首先读取本地客户端证书,然后采用不验证服务端信任证书的方式建立SSLContext
单向认证如下
准备工作
1.下载 bcprov-ext-jdk16-1.46.jar,放入JAVA_HOME \jre\lib\ext下面。
2.修改JAVA_HOME\jre\lib\security\java.security
找到security.provider.1=sun.security.provider.Sun这行,这里有好几行,在最后一行加上
security.provider.10=org.bouncycastle.jce.provider.BouncyCastleProvider
一、生成keystone
1.keytool -genkey -alias asia -keyalg RSA -keystore server.keystore -validity 3600
解释:keytool是jdk下的命令行工具。 alias 随意指定,表示别名。keyalg表示加密算法为RSA,输出文件为server.keystore 这里面需要输入密码(123456)
2.keytool -export -alias asia -file server.cer -keystore server.keystore -storepass 123456
3.keytool -import -alias asia -file server.cer -keystore server_trust.keystore -storepass 123456 -storetype BKS -provider org.bouncycastle.jce.provider.BouncyCastleProvider
二、服务端
编辑${catalina.base}/conf/server.xml
<Connector SSLEnabled="true" clientAuth="false" disableUploadTimeout="true" enableLookups="true"
keystoreFile="${catalina.base}/key/server.keystore" keystorePass="123456" maxSpareThreads="75" maxThreads="200"
minSpareThreads="5" port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol" scheme="https" secure="true"
sslProtocol="TLS"/>
三、客户端
1 /** 2 * 密库,这里用的是BouncyCastle密库 3 */ 4 private static final String CLIENT_KEY_KEYSTORE = "BKS"; 5 6 7 /** 8 * 私钥密码 9 */ 10 private static final String CLIENT_KET_PASSWORD = "123456"; 11 12 /** 13 * keystore路径 14 */ 15 private static final String CLIENT_KEY_KEYSTORE_PATH = "server_trust.keystore"; 16 17 18 19 20 public HttpClient initHttpClient(Context mContext) { 21 if (null == hc) { 22 // 初始化工作 23 try { 24 KeyStore trustStore = KeyStore.getInstance(CLIENT_KEY_KEYSTORE); 25 trustStore.load(mContext.getResources().getAssets().open(CLIENT_KEY_KEYSTORE_PATH), CLIENT_KET_PASSWORD.toCharArray()); 26 27 SSLSocketFactory socketFactory = new SSLSocketFactoryImpl(trustStore); 28 //host认证 29 socketFactory.setHostnameVerifier(new X509HostnameVerifier() { 30 public boolean verify(String arg0, SSLSession arg1) { return true;} 31 public void verify(String arg0, SSLSocket arg1) throws IOException {} 32 public void verify(String arg0, String[] arg1, String[] arg2) throws SSLException {} 33 public void verify(String arg0, X509Certificate arg1) throws SSLException {} 34 }); 35 //设置HTTP参数 36 final HttpParams params = new BasicHttpParams(); 37 HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); 38 HttpProtocolParams.setContentCharset(params, DEFAULT_CHARSET); 39 HttpConnectionParams.setStaleCheckingEnabled(params, false); 40 HttpConnectionParams.setConnectionTimeout(params, timeout); 41 HttpConnectionParams.setSoTimeout(params, timeout); 42 HttpConnectionParams.setSocketBufferSize(params, 8192); 43 HttpClientParams.setRedirecting(params, false); 44 45 SchemeRegistry schReg = new SchemeRegistry(); 46 // schReg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); 47 schReg.register(new Scheme("https", socketFactory, 443)); 48 ClientConnectionManager conManager = new ThreadSafeClientConnManager(params, schReg); 49 hc = new DefaultHttpClient(conManager, params); 50 51 } catch (Exception e) { 52 e.printStackTrace(); 53 return new DefaultHttpClient(); 54 } 55 } 56 return hc; 57 } 58 59 60 61 。。。。。。。。 62 class SSLSocketFactoryImpl extends SSLSocketFactory { 63 /** 64 * 使用协议 65 */ 66 private static final String CLIENT_AGREEMENT = "TLS"; 67 SSLContext sslContext = SSLContext.getInstance(CLIENT_AGREEMENT); 68 69 public SSLSocketFactoryImpl(KeyStore keystore) 70 throws NoSuchAlgorithmException, KeyManagementException, 71 KeyStoreException, UnrecoverableKeyException, IOException, CertificateException { 72 super(keystore); 73 TrustManager tm = new X509TrustManager() { 74 75 @Override 76 public java.security.cert.X509Certificate[] getAcceptedIssuers() { 77 return null; 78 } 79 80 @Override 81 public void checkClientTrusted( 82 java.security.cert.X509Certificate[] chain, 83 String authType) 84 throws java.security.cert.CertificateException { 85 86 } 87 88 @Override 89 public void checkServerTrusted( 90 java.security.cert.X509Certificate[] chain, 91 String authType) 92 throws java.security.cert.CertificateException { 93 94 } 95 }; 96 97 sslContext.init(null, new TrustManager[] { tm }, null); 98 } 99 100 @Override 101 public Socket createSocket(Socket socket, String host, int port, 102 boolean autoClose) throws IOException, UnknownHostException { 103 return sslContext.getSocketFactory().createSocket(socket, host, port, 104 autoClose); 105 } 106 107 @Override 108 public Socket createSocket() throws IOException { 109 return sslContext.getSocketFactory().createSocket(); 110 } 111 }
测试通过 。。。。。。。。。。。。。!!!!
人有两条路要走, 一条是必须走的,一条是想走的,你必须把必须走的路走漂亮,才可以走想走的路。