简体   繁体   中英

SSL Pinning With Volley

I've written a generic GsonRequest class by extending Request of Volley for getting and parsing JSON data from server.My generic class for Volley request as of follow :

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));
        }
    }
}

Now I want to add SSL Pinning to all my API Calls from my App. I couldn't add it out of the box into Request class of Volley. In this blog http://blog.ostorlab.co/2016/05/ssl-pinning-in-android-networking.html , They have explained how to add SSL Pinning in Volley. But they have added that in RequestQueue. But I've implemented Request class of Volley. Anybody has cracked it with Request class rather than RequestQueue Or I need to make a separate API call to validate the certificate .

As far as I know, Volley is one such a powerful networking library with very limited documentation.

Somehow I found the answer that I wanted, Hopefully, this would help someone.

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);
}

Instead of using requestQueue = new Volley().newRequestQueue(context);

Use requestQueue = getPinnedRequestQueue(context);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM