HttpURLConnection的API参见这里
扩展方法及返回
getCipherSuite():获得此次连接过程中用到的加密算法套件
getDefaultHostnameVerifier():获得被该类继承实例的默认认证域名
getDefaultSSLSocketFactory():获得被该类继承实例的默认静态SSL套接字工厂
getHostnameVerifier():获得该实例的认证域名
getLocalCertificates():获得握手阶段发送给服务端的证书
getLocalPrincipal():获得握手阶段发送给服务端的主体对象
getPeerPrincipal():获得定义此次会话的服务端的主体对象
getServerCertificates():获得定义此次会话的服务端的证书链(证书数组,一般是X509证书实例,猜的)
getSSLSocketFactory():获得安全SSL套接字工厂实例,用于建立https安全套接字连接
setDefaultHostnameVerifier(HostnameVerifier v):设置认证域名
setDefaultSSLSocketFactory(SSLSocketFactory sf):
设置SSL套接字工厂
setHostnameVerifier(HostnameVerifier v):…
setSSLSocketFactory(SSLSocketFactory sf): …
### 如何利用HttpsURLConnection建立SSL安全连接(单/双向认证)
懒得BB,先上一段代码:
“`
class UploadSignResultThread extends Thread {
@Override
public void run() {
super.run();
HttpsURLConnection connection = null;
try {
//设置SSLContext
SSLContext sslcontext = SSLContext.getInstance(“TLS”);
sslcontext.init(null, new TrustManager[]{myX509TrustManager}, null);
String head_str = "{\"aid\":" + "\"" + header.getAid() + "\"" + "}";
String payload_str = "{\"signature\":" + "\"" + mySignedData + "\"" + "}";
String nonce_str = header.getNonce();
String HMac = encryptHmac(hexStringToBytes((header.getNonce())),
(base64UrlEncode(head_str.getBytes()) + "."
+ base64UrlEncode(payload_str.getBytes()) + "."
+ base64UrlEncode(nonce_str.getBytes())).getBytes());
String POST_JWT = "SignedMessage=" + base64UrlEncode(head_str.getBytes()) + "."
+ base64UrlEncode(payload_str.getBytes()) + "."
+ HMac;
URL url = new URL(payload.getVerify());
connection = (HttpsURLConnection) url.openConnection();
connection.setSSLSocketFactory(sslcontext.getSocketFactory());
connection.setConnectTimeout(3000);
connection.setRequestMethod("POST");
connection.setHostnameVerifier(SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
byte[] postRes = POST_JWT.getBytes();
// 获得输出流,向服务器输出内容
OutputStream outputStream = connection.getOutputStream();
// 写入数据
outputStream.write(postRes, 0, postRes.length);
outputStream.close();
if (connection.getResponseCode() == 200) {
PostFlag = 0;
} else {
PostFlag = 2;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
}
还是上次的验签过程,现在通过Https认证实现:
1.首先设置与服务端相同的握手协议:
SSLContext sslcontext = SSLContext.getInstance(“TLS”);
这里指定的是TLS,还有SSLv3等
2.设置初始化SSLcontext上下文的信任管理者:
sslcontext.init(null, new TrustManager[]{myX509TrustManager}, null);
这里的myX509TrustManager是我定义的内部类,其实现如下:
private static TrustManager myX509TrustManager = new X509TrustManager() {
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
};
}
这里,getAcceptedIssuers():返回可接受的发行者X509证书数组;
checkServerTrusted(X509Certificate[] chain, String authType):检查服务端证书链,将其与预埋入指定位置(android一般预埋至assets或者res/raw文件夹下)的服务端证书,该方法用主体和发行者比对的方式验证服务端证书链是否可信;
checkClientTrusted(X509Certificate[] chain, String authType):检查客户端证书链,将其与预埋入指定位置(android一般预埋至assets或者res/raw文件夹下)的客户端证书,该方法用主体和发行者比对的方式验证客户端证书链是否可信.
双向认证:实现上述后2个方法;单向认证:实现上述第2个验证服务端证书的方法;
而我,不验证,意思就是完全信任(关系铁,老铁).
3.根据SSLcontext上下文设置套接字工厂:
connection.setSSLSocketFactory(sslcontext.getSocketFactory());
4.设置域名认证,我偷懒默认允许所有,可以new 出个HostnameVerifier实现里面的方法,允许或屏蔽掉一些域名.
connection.setHostnameVerifier(SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
“`