您的位置:首页 > 理论基础 > 计算机网络

Android Volley的使用(三)Volley中如何使用https

2017-06-15 20:09 183 查看

概念

https(Hyper Text TransferProtocol over Secure Socket Layer)简单讲就是在http中加入了SSL(Secure Sockets Layer,安全套接层)层的安全版本。https请求是安全的,所以请求过程中不可以被抓包。

在典型的 SSL 使用场景中,会使用一个包含公钥及与其匹配的私钥的证书配置服务器。让客户端也拥有其信任的一个或多个证书集。如果请求的URL地址时发现证书不在此集合中,则不会信任服务器而请求失败。但是这样做也存在缺点。服务器在后续时间里可能存在升级更强的密钥,使用新的公钥替换证书中的公钥。这时由于客户端不能及时更新的话就会出现问题。

为弥补这些缺点,通常使用来自知名颁发者(称为证书颁发机构 (CA))发放的证书配置服务器。主机平台一般包含其信任的知名 CA 的列表。从 Android 4.2 (Jelly Bean) 开始,Android 目前包含在每个版本中更新的100 多个 CA。CA 具有一个证书和一个私钥,这点与服务器相似。为服务器发放证书时,CA 使用其私钥签署服务器证书。然后,客户端可以验证该服务器是否具有平台已知的 CA 发放的证书。详细可以参考官方说明https://developer.android.com/training/articles/security-ssl.html

实现1

根据上面概念介绍,如果服务器是使用来自知名证书颁发机构发放的证书配置,那么在Android里会自动帮忙我们去验证该证书是否有效,我们在使用Volley请求网络时,根本就是不需要做任何事情,只需要将http URL改成https URL即可。

实现2

如果服务器没有使用第三方知名证书颁发机构发放的证书配置,是通过典型使用场景,即使用一个包含公钥及与其匹配的私钥的证书配置服务器。那么也需要客户端配置与其匹配的证书。我们在《Android Volley的使用(一)基本网络请求》中介绍到可以通过代码

RequestQueue requestQueue =Volley.newRequestQueue(getApplicationContext());


来创建请求队列RequestQueue对象。其实我们从源码中可以发现,newRequestQueue方法还有一个重载的版本:newRequestQueue(Context context, HttpStack stack)。那么客户端配置证书使用如下:

SSLSocketFactory sslSocketFactory =initSSLSocketFactory();
HurlStack stack = new HurlStack(null,sslSocketFactory);
RequestQueue requestQueue =Volley.newRequestQueue(mContext, stack);
private final String RFC ="XXX...";

/**
* 生成SSLSocketFactory
* 这里的代码与之前相比,没有什么不同
*
*@return
*/
private SSLSocketFactoryinitSSLSocketFactory() {
//生成证书:Certificate
CertificateFactory cf = null;
SSLSocketFactory factory = null;
try {
cf = CertificateFactory.getInstance("X.509");
InputStream caInput = new ByteArrayInputStream(RFC.getBytes());                     // 通过证书生成的RFC格式数据字符串
//InputStream caInput = new BufferedInputStream(newFileInputStream("xxx.crt"));       // 证书文件

Certificate ca = null;
try {
ca = cf.generateCertificate(caInput);
} finally {
try {
caInput.close();
} catch (IOException e) {
e.printStackTrace();
}
}

//初始化公钥:keyStore
String keyType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);

//初始化TrustManagerFactory
String algorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory managerFactory =TrustManagerFactory.getInstance(algorithm);
managerFactory.init(keyStore);

//初始化sslContext
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, managerFactory.getTrustManagers(), null);
factory = sslContext.getSocketFactory();

}catch (CertificateException e) {
e.printStackTrace();
}catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}catch (KeyStoreException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}catch (KeyManagementException e) {
e.printStackTrace();
}
return factory;
}


实现3

这种方法属性比较极端的做法,就是跳转证书验证。其实使用https请求验证是否合法,在Volley中主要是HostnameVerifier接口中的verify方法进行验证,所以如果我们在此方法中返回true,则可以跳过证书的验证,实现如下:

新建SsX509TrustManager类,并继承X509TrustManager

public class SsX509TrustManager implementsX509TrustManager {
private static TrustManager[] trustManagers;
private static final X509Certificate[] _AcceptedIssuers = new
X509Certificate[]{};

@Override
public void checkClientTrusted(java.security.cert.X509Certificate[]x509Certificates, String s) throws java.security.cert.CertificateException {
//To change body of implemented methods use File | Settings | FileTemplates.
}

@Override
public void checkServerTrusted(java.security.cert.X509Certificate[]x509Certificates, String s) throws java.security.cert.CertificateException {
//To change body of implemented methods use File | Settings | FileTemplates.
}

public boolean isClientTrusted(X509Certificate[] chain) {
return true;
}

public boolean isServerTrusted(X509Certificate[] chain) {
return true;
}

@Override
public X509Certificate[] getAcceptedIssuers() {
return _AcceptedIssuers;
}

/**
* 允许所有的SSL请求,添加在new StringRequest()之前
*/
public static void allowAllSSL() {
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {

@Override
public boolean verify(String arg0, SSLSession arg1) {
return true;
}

});

SSLContext context = null;
if (trustManagers == null) {
trustManagers = new TrustManager[]{new SsX509TrustManager()};
}

try {
context = SSLContext.getInstance("TLS");
context.init(null, trustManagers, new SecureRandom());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}

HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
}
}


然后在创建请求Request对象前加上一行代码:SsX509TrustManager.allowAllSSL();即可,如:

RequestQueue requestQueue =Volley.newRequestQueue(getApplicationContext());
SsX509TrustManager.allowAllSSL();
StringRequest stringRequest = newStringRequest(Request.Method.GET, "https://kyfw.12306.cn/otn/regist/init",
new Response.Listener<String>() {
@Override
public void onResponse(String s) {
// 请求成功
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
// 请求失败
}
});
requestQueue.add(stringRequest);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android Volley https
相关文章推荐