Android开发中,使用https发送安全请求的实现

什么是HTTPs

https是一种相对安全的传输协议,可以认为是http的安全版本,怎么会安全呢,基础就是靠安全套接字层SSL(Secure Socket Layer),作用

  • 认证用户和服务器,确保数据发送到正确的客户机和服务器;(验证证书)
  • 加密数据以防止数据中途被窃取;(加密)
  • 维护数据的完整性,确保数据在传输过程中不被改变。(摘要算法)

工作原理(转自鸿祥大神的blog)

HTTPS在传输数据之前需要客户端(浏览器)与服务端(网站)之间进行一次握手,在握手过程中将确立双方加密传输数据的密码信息。握手过程的简单描述如下:
浏览器将自己支持的一套加密算法、HASH算法发送给网站。
网站从中选出一组加密算法与HASH算法,并将自己的身份信息以证书的形式发回给浏览器。证书里面包含了网站地址,加密公钥,以及证书的颁发机构等信息。
浏览器获得网站证书之后,开始验证证书的合法性,如果证书信任,则生成一串随机数字作为通讯过程中对称加密的秘钥。然后取出证书中的公钥,将这串数字以及HASH的结果进行加密,然后发给网站。
网站接收浏览器发来的数据之后,通过私钥进行解密,然后HASH校验,如果一致,则使用浏览器发来的数字串使加密一段握手消息发给浏览器。
浏览器解密,并HASH校验,没有问题,则握手结束。接下来的传输过程将由之前浏览器生成的随机密码并利用对称加密算法进行加密。
握手过程中如果有任何错误,都会使加密连接断开,从而阻止了隐私信息的传输。ok,以上的流程不一定完全正确,基本就是这样,当然如果有明显错误欢迎指出。
根据上面的流程,我们可以看到服务器端会有一个证书,在交互过程中客户端需要去验证证书的合法性,对于权威机构颁发的证书当然我们会直接认为合法。对于自己造的证书,那么我们就需要去校验合法性了,也就是说我们只需要让OkhttpClient去信任这个证书就可以畅通的进行通信了。
当然,对于自签名的网站的访问,网上的部分的做法是直接设置信任所有的证书,对于这种做法肯定是有风险的,所以这里我们不去介绍了,有需要自己去查。

应用实例

这里我只是把自己项目中用到的写写。说说思路吧,这里我的网络请求是用的volley实现,用了事件总线otto的框架。

  • 1.我用的是Android studio,因此在build.gradle中的buildTypes的debug和release下的buildConfigField都要把url地址改为https的
  • 2.主要的代码都是在RequestController中实现,直接贴代码

    package com.zjbl.business.controller;
    
    import android.content.Context;
    import android.util.Log;
    
    import com.android.volley.RequestQueue;
    import com.android.volley.toolbox.HurlStack;
    import com.android.volley.toolbox.Volley;
    import com.zjbl.business.BuildConfig;
    import com.zjbl.business.utils.StringRequestWrapper;
    
    import java.io.ByteArrayInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.security.KeyStore;
    import java.security.SecureRandom;
    import java.security.cert.CertificateFactory;
    
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.SSLSocketFactory;
    import javax.net.ssl.TrustManagerFactory;
    
    /**
     * Created by Administrator on 2015/10/22.
     */
    public class RequestController {
    
    private static RequestController instance;
    private RequestQueue mQueue;
    
    private static final String DEBUG_CERTIFICATE = "取得证书的内容";
    private static final String RELEASE_CERTIFICATE = "取得证书的内容";
    private RequestController(Context context) {
        InputStream inputStream = null;
        try {
            if (!BuildConfig.DEBUG){
                    inputStream = new ByteArrayInputStream(RELEASE_CERTIFICATE.getBytes("UTF-8"));
                } else {     
                    inputStream = new ByteArrayInputStream(DEBUG_CERTIFICATE.getBytes("UTF-8"));
                }
            } catch (Exception e){
                Log.e("RequestController", "e = "+e.getMessage()+"-----获取证书信息错误");
            }
            mQueue = Volley.newRequestQueue(context, new HurlStack(null, createCertificates(inputStream)));
    //        mQueue = Volley.newRequestQueue(context);
        }
    
    public static RequestController getRequestControllerInstance(Context context){
        if (instance == null){
            synchronized (RequestController.class){
                if (instance == null){
                    instance = new RequestController(context);
                }
            }
        }
        return instance;
    }
    public RequestQueue getQueue(){
        return mQueue;
    }
    public void request(StringRequestWrapper stringRequestWrapper){
        mQueue.add(stringRequestWrapper.stringRequest);
    }
    
    /**    构造CertificateFactory对象,通过它的generateCertificate(is)方法得到Certificate。
    //    然后讲得到的Certificate放入到keyStore中。
    //    接下来利用keyStore去初始化我们的TrustManagerFactory
    //    由trustManagerFactory.getTrustManagers获得TrustManager[]初始化我们的SSLContext
    //    最后,sslSocketFactory即可
    */
        public SSLSocketFactory createCertificates(InputStream... certificates) {
            SSLSocketFactory sslSocketFactory = null;
            try {
                //CertificateFactory此类定义了用于从相关的编码中生成证书、证书路径 (CertPath) 和证书撤消列表 (CRL) 对象的 CertificateFactory 功能
                CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
                KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
                keyStore.load(null);
                int index = 0;
                for (InputStream certificate : certificates) {
                    String certificateAlias = Integer.toString(index++);
                    keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate));
    
                    try {
                        if (certificate != null)
                            certificate.close();
                    } catch (IOException e) {
                    }
                }
    
                SSLContext sslContext = SSLContext.getInstance("TLS");
    
                TrustManagerFactory trustManagerFactory =
                        TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    
                trustManagerFactory.init(keyStore);
                sslContext.init
                        (
                                null,
                                trustManagerFactory.getTrustManagers(),
                                new SecureRandom()
                        );
                Log.e("RequestController", "sslContext = " + sslContext.getProtocol() + "---" + sslContext.getServerSocketFactory() + "---" + sslContext.getSocketFactory()
                        + "----" + sslContext.getDefaultSSLParameters());
                sslSocketFactory = sslContext.getSocketFactory();
    
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                return sslSocketFactory;
            }
    
        }
    }
    
总结

上面的代码主要对https的操作都在createCertificates方法中,然后在RequestController(content)方法中实例化整个volley队列,一般使用时需要具体的去继承该类然后在对应的类中实现对应的方法,在其他页面调用,会是如下的用法:

         RequestController.getRequestControllerInstance(this.getActivity()).request(requestWrapper);
  • 还有另外一种调用方法,新建一个controller,然其他类去继承该类,而该controller中具体的代码:

    public class Controller {
        protected  Context context;
        protected RequestQueue mQueue;
        protected Controller(BackgroundBus backgroundBus, Context context) {
            backgroundBus.register(this);
            this.context=context;
            mQueue = RequestController.getRequestControllerInstance(context).getQueue();
    //        mQueue = Volley.newRequestQueue(context);
        }
        public void request(StringRequestWrapper stringRequestWrapper){
            mQueue.add(stringRequestWrapper.stringRequest);
        }
    }
    

上面的例子,也不算是很清晰,用的时候,算是搬运工了,加油

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android Studio是一款用于开发Android应用程序的集成开发环境(IDE),它通过提供丰富的功能和工具,让开发者可以更轻松地构建和调试Android应用。 要发送POST请求,我们需要在项目的build.gradle文件添加网络请求库的依赖。例如,我们可以使用OkHttp库,可以在build.gradle文件的dependencies块添加以下代码: implementation 'com.squareup.okhttp3:okhttp:4.9.0' 接下来,在我们的活动或片段类创建一个方法来发送POST请求。这种发送请求的简便方法是使用AsyncTask类的doInBackground()方法在后台线程执行网络请求。示例如下: private class MyAsyncTask extends AsyncTask<String, Void, String> { @Override protected String doInBackground(String... params) { String url = params[0]; String postData = params[1]; OkHttpClient client = new OkHttpClient(); RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), postData); Request request = new Request.Builder() .url(url) .post(body) .build(); try { Response response = client.newCall(request).execute(); return response.body().string(); } catch (IOException e) { e.printStackTrace(); } return null; } @Override protected void onPostExecute(String result) { // 在这里处理响应结果 } } 然后,在我们的活动或片段类创建一个实例并执行AsyncTask来发送POST请求。我们需要传递URL和要发送的数据作为参数。示例如下: String url = "https://example.com/api"; String postData = "{ \"name\": \"John\", \"age\": 30 }"; MyAsyncTask task = new MyAsyncTask(); task.execute(url, postData); 在AsyncTask的onPostExecute()方法,我们可以处理响应结果,并更新UI或执行其他操作。这里的示例代码只是简单地打印响应结果,你可以根据自己的需求进行相应的处理。 这就是使用Android Studio发送POST请求的简单示例。请注意,这只是一个基本示例,实际应用可能需要处理更多的逻辑和错误处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值