Android-工作遭遇-URLConnection原生请求http和https忽略证书
16lz
2021-01-24
Android网络请求框架非常多,github一搜就是一堆.我的博客就不讲这些,我就讲讲原生已经够用了.
HttpURLConnection是Android提供的一个网络请求库,个人认为,还是蛮好用的.
HttpsURLConnection是本身就继承自HttpURLConnection的类
首先是忽略证书这一块.有些请求涉及到请求证书.加载证书似乎很麻烦.(不麻烦,我不想加载)
首先需要初始化,一般我喜欢封装一个工具类,然后在静态代码块中,进行初始化
static { try { ctx = SSLContext.getInstance("TLS"); ctx.init(new KeyManager[0], new TrustManager[]{new DefaultTrustManager(null)}, new SecureRandom()); ctx.getClientSessionContext().setSessionTimeout(15); ctx.getClientSessionContext().setSessionCacheSize(1000); socketFactory = ctx.getSocketFactory(); } catch (Exception ignored) { } verifier = new HostnameVerifier(); }
其中的new TrustManager[]{new WebUtils.DefaultTrustManager(null)}.只是继承了X509TrustManager进行使用
private static class DefaultTrustManager implements X509TrustManager { private DefaultTrustManager(Object o) { } public X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } }
HostnameVerifier中我对忽略规则做了处理,特殊请求的url,证书还是需要的
Pattern.compile("([0-9a-fA-F]*:[0-9a-fA-F:.]*)|([\\d.]+)");
如果匹配上这条正则.则需要ssl协议
关键点在于获取Connection的时候做的处理
// new URL即可,请求方法,post还是get.Content-type,一般都是utf-8 private static HttpURLConnection getConnection(URL url, String method, String ctype) throws IOException { HttpURLConnection conn = null; if ("https".equals(url.getProtocol())) {// ssl证书管理在这里 HttpsURLConnection connHttps = (HttpsURLConnection) url.openConnection(); connHttps.setSSLSocketFactory(socketFactory); connHttps.setHostnameVerifier(verifier); conn = connHttps; } else { conn = (HttpURLConnection) url.openConnection(); } conn.setRequestMethod(method); conn.setAllowUserInteraction(true); conn.setInstanceFollowRedirects(true); if (method.equalsIgnoreCase("post")) { conn.setDoInput(true); conn.setDoOutput(true); conn.setUseCaches(false); } // cookie也可以在这里设置// conn.setRequestProperty("Set-Cookie", ""); conn.setRequestProperty("User-Agent",""); conn.setRequestProperty("Content-Type", ""); return conn; }
使用也是非常的简单
public static byte[] doGet(String url, Map params) { HttpURLConnection conn = null; String responseBody = null; byte[] bytes = new byte[0]; try {// 这里我写了一个方法.把get请求的参数作为拼接 conn = getConnection(new URL(getQueryUrl(url, params)), "GET", "*/*;charset=utf-8"); conn.setReadTimeout(0); conn.setConnectTimeout(0); bytes = readInputStream(conn.getInputStream()); } catch (Exception e) { e.printStackTrace(); } finally { if (conn != null) { conn.disconnect(); } } return bytes; }
附上完整工具类
public class WebUtils { private static final String DEFAULT_CHARSET = "UTF-8"; private static final String METHOD_POST = "POST"; private static final String METHOD_GET = "GET"; private static SSLContext ctx = null; private static HostnameVerifier verifier = null; private static SSLSocketFactory socketFactory = null; private WebUtils() { } public static String doPostStringResponse(String url, String json) { Log.d("WebUtils", url); HttpURLConnection conn = null; String responseBody = null; try { conn = getConnection(new URL(url), "POST", "application/json;charset=utf-8"); conn.setReadTimeout(0); conn.setConnectTimeout(0);// post发送json数据 if (!TextUtils.isEmpty(json)) { byte[] bytes = json.getBytes(); conn.setRequestProperty("Content-Length", bytes.length + ""); OutputStream outputStream = conn.getOutputStream(); outputStream.write(bytes); outputStream.flush(); outputStream.close(); } byte[] bytes = readInputStream(conn.getInputStream()); responseBody = new String(bytes, "utf-8"); } catch (Exception e) { e.printStackTrace(); } finally { if (conn != null) { conn.disconnect(); } } return responseBody; } public static byte[] doGet(String url) { return doGet(url, null); } public static byte[] doGet(String url, Map params) { HttpURLConnection conn = null; String responseBody = null; byte[] bytes = new byte[0]; try { conn = getConnection(new URL(getQueryUrl(url, params)), "GET", "*/*;charset=utf-8"); conn.setReadTimeout(0); conn.setConnectTimeout(0); bytes = readInputStream(conn.getInputStream()); } catch (Exception e) { e.printStackTrace(); } finally { if (conn != null) { conn.disconnect(); } } return bytes; } private static byte[] readInputStream(InputStream inputStream) throws IOException { byte[] buffer = new byte[1024]; int len = 0; ByteArrayOutputStream bos = new ByteArrayOutputStream(); while ((len = inputStream.read(buffer)) != -1) { bos.write(buffer, 0, len); } bos.close(); inputStream.close(); return bos.toByteArray(); } private static HttpURLConnection getConnection(URL url, String method, String ctype) throws IOException { HttpURLConnection conn = null; if ("https".equals(url.getProtocol())) { HttpsURLConnection connHttps = (HttpsURLConnection) url.openConnection(); connHttps.setSSLSocketFactory(socketFactory); connHttps.setHostnameVerifier(verifier); conn = connHttps; } else { conn = (HttpURLConnection) url.openConnection(); } conn.setRequestMethod(method); conn.setAllowUserInteraction(true); conn.setInstanceFollowRedirects(true);// post方法必须加上,get方法是不需要这些,否则会失败 if (method.equalsIgnoreCase("post")) { conn.setDoInput(true); conn.setDoOutput(true); conn.setUseCaches(false); } // cookie也可以在这里设置// conn.setRequestProperty("Set-Cookie", ""); conn.setRequestProperty("User-Agent", Settings.UA); conn.setRequestProperty("Content-Type", ctype); return conn; } static { try { ctx = SSLContext.getInstance("TLS"); ctx.init(new KeyManager[0], new TrustManager[]{new WebUtils.DefaultTrustManager(null)}, new SecureRandom()); ctx.getClientSessionContext().setSessionTimeout(15); ctx.getClientSessionContext().setSessionCacheSize(1000); socketFactory = ctx.getSocketFactory(); } catch (Exception ignored) { } verifier = new HostnameVerifier(); } /** * 拼接get数据 * * @param url 地址 * @param params get参数 * @return */ private static String getQueryUrl(String url, Map params) { StringBuilder neoUrl = new StringBuilder(url); if (params != null) { neoUrl.append("?"); for (Map.Entry stringStringEntry : params.entrySet()) { neoUrl.append(stringStringEntry.getKey()).append("=").append(stringStringEntry.getValue()).append("&"); } neoUrl = new StringBuilder(neoUrl.substring(0, neoUrl.length() - 1)); } return neoUrl.toString(); } private static class DefaultTrustManager implements X509TrustManager { private DefaultTrustManager(Object o) { } public X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } } }
以及HostnameVerifier
public class HostnameVerifier implements javax.net.ssl.HostnameVerifier { public static final HostnameVerifier INSTANCE = new HostnameVerifier(); private static final int ALT_DNS_NAME = 2; private static final int ALT_IPA_NAME = 7; private static final Pattern VERIFY_AS_IP_ADDRESS = Pattern.compile("([0-9a-fA-F]*:[0-9a-fA-F:.]*)|([\\d.]+)"); HostnameVerifier() { } public boolean verify(String host, SSLSession session) { try { Certificate[] certificates = session.getPeerCertificates(); return this.verify(host, (X509Certificate)certificates[0]); } catch (SSLException var4) { return false; } } public boolean verify(String host, X509Certificate certificate) { return verifyAsIpAddress(host)?this.verifyIpAddress(host, certificate):this.verifyHostname(host, certificate); } private boolean verifyIpAddress(String ipAddress, X509Certificate certificate) { List altNames = getSubjectAltNames(certificate, 7); int i = 0; for(int size = altNames.size(); i < size; ++i) { if(ipAddress.equalsIgnoreCase((String)altNames.get(i))) { return true; } } return false; } private boolean verifyHostname(String hostname, X509Certificate certificate) { hostname = hostname.toLowerCase(Locale.US); List altNames = getSubjectAltNames(certificate, 2); Iterator var4 = altNames.iterator(); String altName; do { if(!var4.hasNext()) { return false; } altName = (String)var4.next(); } while(!this.verifyHostname(hostname, altName)); return true; } public static List allSubjectAltNames(X509Certificate certificate) { List altIpaNames = getSubjectAltNames(certificate, 7); List altDnsNames = getSubjectAltNames(certificate, 2); List result = new ArrayList(altIpaNames.size() + altDnsNames.size()); result.addAll(altIpaNames); result.addAll(altDnsNames); return result; } private static List getSubjectAltNames(X509Certificate certificate, int type) { ArrayList result = new ArrayList(); try { Collection<?> subjectAltNames = certificate.getSubjectAlternativeNames(); if(subjectAltNames == null) { return Collections.emptyList(); } else { Iterator var4 = subjectAltNames.iterator(); while(var4.hasNext()) { Object subjectAltName = var4.next(); List<?> entry = (List)subjectAltName; if(entry != null && entry.size() >= 2) { Integer altNameType = (Integer)entry.get(0); if(altNameType != null && altNameType.intValue() == type) { String altName = (String)entry.get(1); if(altName != null) { result.add(altName); } } } } return result; } } catch (CertificateParsingException var9) { return Collections.emptyList(); } } public boolean verifyHostname(String hostname, String pattern) { if(hostname != null && hostname.length() != 0 && !hostname.startsWith(".") && !hostname.endsWith("..")) { if(pattern != null && pattern.length() != 0 && !pattern.startsWith(".") && !pattern.endsWith("..")) { if(!hostname.endsWith(".")) { hostname = hostname + '.'; } if(!pattern.endsWith(".")) { pattern = pattern + '.'; } pattern = pattern.toLowerCase(Locale.US); if(!pattern.contains("*")) { return hostname.equals(pattern); } else if(pattern.startsWith("*.") && pattern.indexOf(42, 1) == -1) { if(hostname.length() < pattern.length()) { return false; } else if("*.".equals(pattern)) { return false; } else { String suffix = pattern.substring(1); if(!hostname.endsWith(suffix)) { return false; } else { int suffixStartIndexInHostname = hostname.length() - suffix.length(); return suffixStartIndexInHostname <= 0 || hostname.lastIndexOf(46, suffixStartIndexInHostname - 1) == -1; } } } else { return false; } } else { return false; } } else { return false; } } public static boolean verifyAsIpAddress(String host) { return VERIFY_AS_IP_ADDRESS.matcher(host).matches(); }}
更多相关文章
- Android之-----GridView使用的方法总结
- Android(安卓)Handler那些事儿(二)——几个关键类之间的关系
- Flutter(三):实现Flutter代码调用Android原生代码(创建WebView Plu
- Android事件处理之使用异步任务执行下载
- Android(安卓)数字证书详
- Android属性动画完全解析(中),ValueAnimator和ObjectAnimator的高
- Android(安卓)Context简介
- Android中关于SQLite数据库的一些知识
- Android超精准计步器开发-Dylan计步