首页 > 系统 > Android > 正文

android 访问https服务器

2019-11-07 22:48:42
字体:
来源:转载
供稿:网友

    之前,我讲了如何让tomcat支持https访问,当时浏览器通过https:localhost:8443即可访问tomcat。可是android此时如何访问已经搭建好的tomcat的https了?我在网上找了很多资料,发现还是有问题,后来自己改了一些,终于是做出来了。

1.搭建tomcat的https服务器。

这个,我之前的博客已经讲过,所有不在细讲了。

2.将搭建tomcat服务器时生成的server.cer证书放在android的assets目录下,应为客户端用https访问时需要检测服务器的证书是否符合要求。

3.编写一个类继承X509TrustManager,X509TrustManager是证书信任管理器类,我们可以自己实现该接口,让它信任我们指定的证书。

自己实现了信任管理器类,如何使用呢?类HttpsURLConnection似乎并没有提供方法设置信任管理器。其实,HttpsURLConnection通过SSLSocket来建立与HTTPS的安全连接,SSLSocket对象是由SSLSocketFactory生成的。HttpsURLConnection提供了方法setSSLSocketFactory(SSLSocketFactory)设置它使用的SSLSocketFactory对象。SSLSocketFactory通过SSLContext对象来获得,在初始化SSLContext对象时,可指定信任管理器对象。

public class TrustAllCertsManager implements X509TrustManager {    @Override    public void checkClientTrusted(X509Certificate[] chain, String authType)            throws CertificateException {        // Do nothing -> accept any certificates    }    @Override    public void checkServerTrusted(X509Certificate[] chain, String authType)            throws CertificateException {        // Do nothing -> accept any certificates    }    @Override    public X509Certificate[] getAcceptedIssuers() {        return new X509Certificate[0];    }}

4.编写一个类实现HostnameVerifier接口,此类是用于主机名验证的基接口。

在握手期间,如果 URL 的主机名和服务器的标识主机名不匹配,则验证机制可以回调此接口的实现程序来确定是否应该允许此连接。

策略可以是基于证书的或依赖于其他验证方案。

当验证 URL 主机名使用的默认规则失败时使用这些回调。

public class VerifyEverythinGhostnameVerifier implements HostnameVerifier {    @Override    public boolean verify(String hostname, SSLsession session) {        return true;    }}

此时,我设置对所有主机都可以访问。

5.实例化服务器的证书。

PRivate TrustManager[] createTrustManager() {    BufferedInputStream cerInputStream = null;    try {        // 获取客户端存放的服务器公钥证书        cerInputStream = new BufferedInputStream(getAssets().open("server.cer"));        // 根据公钥证书生成Certificate对象        CertificateFactory cf = CertificateFactory.getInstance("X.509");        Certificate ca = cf.generateCertificate(cerInputStream);        Log.e("TAG", "ca=" + ((X509Certificate) ca).getSubjectDN());        // 生成包含当前CA证书的keystore        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());        keyStore.load(null, null);        keyStore.setCertificateEntry("ca", ca);        // 使用包含指定CA证书的keystore生成TrustManager[]数组        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);        tmf.init(keyStore);        return tmf.getTrustManagers();    } catch (CertificateException e) {        e.printStackTrace();    } catch (IOException e) {        e.printStackTrace();    } catch (KeyStoreException e) {        e.printStackTrace();    } catch (NoSuchAlgorithmException e) {        e.printStackTrace();    } finally {        if (cerInputStream != null) {            try {                cerInputStream.close();            } catch (IOException e) {                e.printStackTrace();            }        }    }    return null;}

上面的代码比较固定,其中server.cer是配置tomcat时的服务器证书。具体我也不是很清楚,可以去百度找一下。

6.具体实现https请求。

 private void httpsRequest(){        String name="健康科技";        String pass="123456";        TrustManager[] trustManager = createTrustManager();//        TrustManager[] trustManager = new TrustManager[]{new TrustAllCertsManager()};        SSLContext sslContext = null;        if (trustManager == null) {            Log.e("TAG", "tmf create failed!");            return;        }        try {            sslContext = SSLContext.getInstance("SSL");            sslContext.init(null, trustManager, new java.security.SecureRandom());        } catch (NoSuchAlgorithmException e) {            // do nothing        }catch (KeyManagementException e) {            // do nothing        }        HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());        HttpsURLConnection httpsURLConnection = null;        BufferedReader reader = null;        URL url = null;        try {            url = new URL("https://192.168.1.190:8443/MyWeb/HttpServlet");            httpsURLConnection = (HttpsURLConnection) url.openConnection();            httpsURLConnection.setHostnameVerifier(new VerifyEverythingHostnameVerifier());            httpsURLConnection.setConnectTimeout(5000);            httpsURLConnection.setDoInput(true);            httpsURLConnection.setUseCaches(false);            //将用户名和密码放入HashMap中            Map<String,String> params=new HashMap<String,String>();            params.put("userName", name);            params.put("passWord", pass);            StringBuffer stringBuffer = new StringBuffer();        //存储封装好的请求体信息            try {                for(Map.Entry<String, String> entry : params.entrySet()) {                    stringBuffer.append(entry.getKey())                            .append("=")                            .append(URLEncoder.encode(entry.getValue(), "UTF-8"))                            .append("&");                }                stringBuffer.deleteCharAt(stringBuffer.length() - 1);    //删除最后的一个"&"            } catch (Exception e) {                e.printStackTrace();            }            byte[] data=stringBuffer.toString().getBytes();            httpsURLConnection.setRequestMethod("POST");   //设置请求为POST            httpsURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");            httpsURLConnection.setRequestProperty("Content-Length", String.valueOf(data.length));            httpsURLConnection.connect();            OutputStream outputStream = httpsURLConnection.getOutputStream();            outputStream.write(data);            reader = new BufferedReader(new InputStreamReader(httpsURLConnection.getInputStream()));            StringBuilder sBuilder = new StringBuilder();            String line;            while ((line = reader.readLine()) != null) {                sBuilder.append(line);            }            Log.e("TAG", "Wiki content=" + sBuilder.toString());            final String s=sBuilder.toString();            runOnUiThread(new Runnable() {                @Override                public void run() {                    mTextView.setText(s.toString());                }            });        } catch (MalformedURLException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        }    }

到这来,客户端就可以做https请求了,不过服务器的tomcat需要自己写一个简单的HttpServlet,这个很简单,自己完全可以百度。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表