我通过扩展Request of Volley来获取和解析来自server的JSON数据,编写了一个通用的GsonRequest类。我的Volley请求的泛型类如下:
public class GsonRequest<T> extends Request<T> {
private final Gson gson = new Gson();
private final Class<T> clazz;
private final Map<String, String> headers;
private final Listener<T> listener;
/**
* Make a GET request and return a parsed object from JSON. Assumes
* {@link Method#GET}.
*
* @param url
* URL of the request to make
* @param clazz
* Relevant class object, for Gson's reflection
* @param headers
* Map of request headers
*/
public GsonRequest(String url, Class<T> clazz, Map<String, String> headers, Listener<T> listener, ErrorListener errorListener) {
super(Method.GET, url, errorListener);
this.clazz = clazz;
this.headers = headers;
this.listener = listener;
}
/**
* Like the other, but allows you to specify which {@link Method} you want.
*
* @param method
* @param url
* @param clazz
* @param headers
* @param listener
* @param errorListener
*/
public GsonRequest(int method, String url, Class<T> clazz, Map<String, String> headers, Listener<T> listener, ErrorListener errorListener) {
super(method, url, errorListener);
this.clazz = clazz;
this.headers = headers;
this.listener = listener;
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
return headers != null ? headers : super.getHeaders();
}
@Override
protected void deliverResponse(T response) {
listener.onResponse(response);
}
@Override
protected Response<T> parseNetworkResponse(NetworkResponse response) {
try {
String json = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
return Response.success(gson.fromJson(json, clazz), HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
} catch (JsonSyntaxException e) {
return Response.error(new ParseError(e));
}
}
}
现在我想从我的应用程序添加SSL Pinning到我的所有API调用。 我无法将它从开箱即用的Feed类中添加到Volley中。 在此博客http://blog.ostorlab.co/2016/05/ssl-pinning-in-android-networking.html中,他们已经解释了如何在Volley中添加SSL Pinning。但是他们在RequestQueue中添加了它。但是我已经实现了Volley的Request类。任何人都使用Request类而不是RequestQueue破解它或者我需要进行单独的API调用来验证证书。
答案 0 :(得分:2)
据我所知,Volley是一个功能强大的网络库,文档非常有限。
不知怎的,我找到了我想要的答案,希望这会对某人有所帮助。
private RequestQueue getPinnedRequestQueue(Context context) throws CertificateException, IOException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
// Generate the certificate using the certificate file under res/raw/cert.cer
InputStream caInput = new BufferedInputStream(context.getResources().openRawResource(R.raw.your_ssl_cert));
final Certificate ca = cf.generateCertificate(caInput);
caInput.close();
// Create a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore trusted = KeyStore.getInstance(keyStoreType);
trusted.load(null, null);
trusted.setCertificateEntry("ca", ca);
// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(trusted);
// Create an SSLContext that uses our TrustManager
SSLContext sslContext = SSLContext.getInstance("TLSV1.2");
sslContext.init(null, tmf.getTrustManagers(), null);
SSLSocketFactory sf = sslContext.getSocketFactory();
HurlStack hurlStack = new HurlStack(null, sf) {
@Override
protected HttpURLConnection createConnection(URL url) throws IOException {
LogUtil.info(TAG, "Before createConnection");
HttpsURLConnection httpsURLConnection = (HttpsURLConnection) super.createConnection(url);
LogUtil.info(TAG, "After createConnection");
httpsURLConnection.setHostnameVerifier(new HostnameVerifier() {
@DebugLog
@Override
public boolean verify(String hostName, SSLSession sslSession) {
String certificateDomainName = ((X509Certificate) ca).getSubjectDN().toString();
LogUtil.info(TAG, "Index : " + certificateDomainName.indexOf("CN=") + " Len : " + certificateDomainName.codePointCount(certificateDomainName.indexOf("CN="), certificateDomainName.indexOf(",")));
String certificateName = certificateDomainName.substring(certificateDomainName.indexOf("CN="), certificateDomainName.codePointCount(certificateDomainName.indexOf("CN="), certificateDomainName.indexOf(",")));
certificateName = certificateName.replace("CN=", "");
LogUtil.info(TAG, "hostName : " + hostName + " certificateName : " + certificateName);
if (certificateName.isEmpty())
return false;
return certificateName.equals(hostName);
}
});
return httpsURLConnection;
}
};
return new Volley().newRequestQueue(context, hurlStack);
}
而不是使用requestQueue = new Volley().newRequestQueue(context);
使用requestQueue = getPinnedRequestQueue(context);