使用 Volley 固定 SSL [英] SSL Pinning With Volley

查看:31
本文介绍了使用 Volley 固定 SSL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我通过扩展 Volley 的请求编写了一个通用的 GsonRequest 类,用于从服务器获取和解析 JSON 数据.我的 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));
        }
    }
}

现在我想将 SSL Pinning 添加到我的应用程序中的所有 API 调用.我无法将它开箱即用地添加到 Volley 的 Request 类中.在此博客中 http://blog.ostorlab.co/2016/05/ssl-pinning-in-android-networking.html ,他们已经解释了如何在 Volley 中添加 SSL Pinning.但是他们在 RequestQueue 中添加了它.但是我已经实现了 Volley 的 Request 类.有人用 Request 类而不是 RequestQueue 破解了它,或者我需要进行单独的 API 调用来验证证书.

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 .

推荐答案

据我所知,Volley 是一个如此强大的网络库,但文档非常有限.

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

而不是使用 requestQueue = new Volley().newRequestQueue(context);

使用requestQueue = getPinnedRequestQueue(context);

这篇关于使用 Volley 固定 SSL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆