安卓okhttp3,retrofit2调用ssl建立post请求(访问华为IoT平台对设备下发命令为例)

文章目录

    • 前言
    • 工具类
      • SSLHelper类
      • HttpsUtils类
    • 主函数

前言

安卓app作为应用侧访问华为物联网平台需要携带证书,Android的私钥和信任证书的格式必须是BKS格式的,可用openssl等工具进行证书格式转换(具体操作)转换完成后在src/mian目录下创建assets文件夹,不可直接创建文件夹(创建方式),并将bks证书(注意客户端和服务端证书都是bks类型)复制到文件夹内

工具类

SSLHelper类

public class SSLHelper{
	private static final String TAG = "SSLHelper";
    private static final String CLIENT_PRI_KEY = "client.bks";
    private static final String TRUSTSTORE_PUB_KEY = "truststore.bks";
    private static final String CLIENT_BKS_PW = "IoM@1234";//证书密钥
    private static final String TRUSTSTORE_BKS_PW = "Huawei@123";//证书密钥
    private static final String KEYSTORE_TYPE = "BKS";
    private static final String PROTOCOL_TYPE = "TLS";
    private static final String CERTIFICATE_STANDARD ="X509";

	public static SSLSocketFactory getSSLCertificate(Context context){
		SSLSocketFactory sslSocketFactory  = null;
		try {
            //服务端需要验证的客户端证书,客户端的keystore(Keytool将密钥(key)和证书(certificates)存在一个称为keystore的文件中)
            KeyStore keyStore = KeyStore.getInstance(KEYSTORE_TYPE);
            //客户端信任服务端的证书
            KeyStore trustStore = KeyStore.getInstance(KEYSTORE_TYPE);

            //读取证书
            InputStream ksIn = context.getAssets().open(CLIENT_PRI_KEY);
            InputStream tsIn = context.getAssets().open(TRUSTSTORE_PUB_KEY);

            //加载证书
            keyStore.load(ksIn,CLIENT_BKS_PW.toCharArray());
            trustStore.load(tsIn,TRUSTSTORE_BKS_PW.toCharArray());
            ksIn.close();
            tsIn.close();

            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(CERTIFICATE_STANDARD);
            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(CERTIFICATE_STANDARD);
            trustManagerFactory.init(trustStore);
            keyManagerFactory.init(keyStore,CLIENT_BKS_PW.toCharArray());

            //初始化SSLContext
            SSLContext sslContext = SSLContext.getInstance(PROTOCOL_TYPE);
            sslContext.init(keyManagerFactory.getKeyManagers(),trustManagerFactory.getTrustManagers(),new java.security.SecureRandom());

            sslSocketFactory = sslContext.getSocketFactory();
            return sslSocketFactory;
        } catch (KeyStoreException e) {
           Log.d("KeyStoreException",e.toString());
           e.printStackTrace();
        } catch (IOException e) {
            Log.d("IOException",e.toString());
            e.printStackTrace();
        } catch (CertificateException e) {
            Log.d("CertificateException",e.toString());
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            Log.d("NoSuchAlgorithm",e.toString());
            e.printStackTrace();
        } catch (UnrecoverableKeyException e) {
            Log.d("UnrecoverableKey",e.toString());
            e.printStackTrace();
        } catch (KeyManagementException e) {
            Log.d("KeyManagement",e.toString());
            e.printStackTrace();
        }
        return sslSocketFactory;
	}
}

HttpsUtils类

public class HttpsUtils {
    public  static class SSLParams{
        public SSLSocketFactory sslSocketFactory;
        public X509TrustManager trustManager;
    }

    public static SSLParams getSSLSocketFactory(InputStream[] certificates, InputStream bksFile, String password){
        SSLParams sslParams = new SSLParams();
        try {
            TrustManager[] trustManagers = prepareTrustManager(certificates);
            KeyManager[] keyManagers = prepareKeyManager(bksFile,password);
            SSLContext sslContext = SSLContext.getInstance("TLS");
            X509TrustManager trustManager = null;
            if (trustManagers != null){
                trustManager = new MyTrustManager(chooseTrustManager(trustManagers));
            }else {
                trustManager = new UnSafeTrustManager();
            }
            sslContext.init(keyManagers, new TrustManager[]{trustManager},null);
            sslParams.sslSocketFactory = sslContext.getSocketFactory();
            sslParams.trustManager = trustManager;
            return sslParams;
        } catch (NoSuchAlgorithmException e) {
            throw new AssertionError(e);
        } catch (KeyStoreException e) {
            throw new AssertionError(e);
        } catch (KeyManagementException e) {
            throw new AssertionError(e);
        }
    }

    public static class UnSafeHostnameVerifier implements HostnameVerifier{
        @Override
        public boolean verify(String s, SSLSession sslSession) {
            return true;
        }
    }

    public static class UnSafeTrustManager implements X509TrustManager{
        @Override
        public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

        }

        @Override
        public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[]{};
        }
    }

    private static TrustManager[] prepareTrustManager(InputStream... certificates){
        if (certificates == null || certificates.length <= 0){return null;}
        try {
            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));
                if (certificate != null){
                    certificate.close();
                }
            }
            TrustManagerFactory trustManagerFactory = null;
            trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(keyStore);
            TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
            return trustManagers;
        } catch (CertificateException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    private static KeyManager[] prepareKeyManager(InputStream bksFile, String password){
        if (bksFile == null || password == null){return null;}

        try {
            KeyStore clientKeyStore = KeyStore.getInstance("BKS");
            clientKeyStore.load(bksFile,password.toCharArray());
            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            keyManagerFactory.init(clientKeyStore,password.toCharArray());
            return keyManagerFactory.getKeyManagers();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        } catch (CertificateException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (UnrecoverableKeyException e) {
            e.printStackTrace();
        }
        return null;
    }

    private static X509TrustManager chooseTrustManager(TrustManager[] trustManagers){
        for (TrustManager trustManager : trustManagers){
            if (trustManager instanceof X509TrustManager){
                return (X509TrustManager) trustManager;
            }
        }
        return null;
    }

    private static class MyTrustManager implements X509TrustManager{
        private X509TrustManager defaultTrustManager;
        private X509TrustManager localTrustManager;

        public MyTrustManager(X509TrustManager localTrustManager) throws NoSuchAlgorithmException, KeyStoreException {
            TrustManagerFactory var4 = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            var4.init((KeyStore) null);
            defaultTrustManager = chooseTrustManager(var4.getTrustManagers());
            this.localTrustManager = localTrustManager;
        }
        @Override
        public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

        }

        @Override
        public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
            try {
                defaultTrustManager.checkServerTrusted(x509Certificates,s);
            } catch (CertificateException e) {
                localTrustManager.checkServerTrusted(x509Certificates,s);
            }
        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[0];
        }
    }
}

主函数

本案例需要post的数据较为复杂,可根据自身情况删减(retrofit2的相关资料)

public class MainActivity extends AppCompatActivity {
    private Button btn,btnOpen;
    private TextView tv;
    public static final MediaType JSON = MediaType.parse("application/json;charset=utf-8");
    int flag = 0;

    public interface ApiLogin{
        @POST("***")
        @FormUrlEncoded
        Call<ResponseBody> testFromUrlEncoded(@Field("appId") String appID,@Field("secret") String secret);
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv = findViewById(R.id.tv);
        btn = findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                login();
            }
        });
        btnOpen = findViewById(R.id.btn_open);
        btnOpen.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                change();
            }
        });
    }
    public void login(){
        //创建日志拦截器,用于日志打印
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
		//调用ssl建立连接
        OkHttpClient httpClient = new OkHttpClient().newBuilder()
                .addInterceptor(interceptor)
                .sslSocketFactory(SSLHelper.getSSLCertificate(this),new HttpsUtils.UnSafeTrustManager())
                .hostnameVerifier(new HttpsUtils.UnSafeHostnameVerifier()).build();
		
        String baseUrl = "***";//url
        String appId = "***";//需要post的表单数据
        String secret = "***";//需要post的表单数据
        Retrofit retrofit = new Retrofit.Builder().baseUrl(baseUrl).client(httpClient)
                .addConverterFactory(ScalarsConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create()).build();
        final ApiLogin request = retrofit.create(ApiLogin.class);
        Call<ResponseBody> call = request.testFromUrlEncoded(appId,secret);//绑定表单数据
        call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                final String content;
                try {
                	//解析请求返回的json数据
                    content = response.body().string();
                    Log.d("response",content);
                    Gson gson = new Gson();
                    loginBean loginBean = gson.fromJson(content, com.example.hworder.json.loginBean.class);
                    final String accessToken = loginBean.getAccessToken();
                    Log.d("accessToken",accessToken);
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            tv.setText(accessToken);//
                        }
                    });
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                Log.d("fail",t.toString());
            }
        });
    }
    public void change(){
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

        final String accessToken = (String) tv.getText();
        Log.d("getAccessToken",accessToken);

        String url = "***";

        Map changeMap = changeBody(flag);//post发送的json数据
        Gson gson = new Gson();
        String changeStr = gson.toJson(changeMap);//将json数据转换成字符串
        Log.d("changeStr",changeStr);

        OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();
        clientBuilder.addInterceptor(new Interceptor() {
            @Override
            public okhttp3.Response intercept(Chain chain) throws IOException {
                Request original = chain.request();
                //设置请求头
                Request request = original.newBuilder()
                        .header("***","***")
                        .header("***","***")
                        .header("Content-Type","application/json").build();
                return chain.proceed(request);
            }
        });
        OkHttpClient client = clientBuilder.addInterceptor(interceptor)
                .sslSocketFactory(SSLHelper.getSSLCertificate(this),new HttpsUtils.UnSafeTrustManager())
                .hostnameVerifier(new HttpsUtils.UnSafeHostnameVerifier())
                .build();
        RequestBody requestBody = RequestBody.create(JSON,changeStr);//根据json数据转化的字符串创建请求体
        Request request = new Request.Builder().post(requestBody)
                .url("***").build();
        client.newCall(request).enqueue(new okhttp3.Callback() {
            @Override
            public void onFailure(okhttp3.Call call, final IOException e) {
                Log.d("changeFail",e.toString());
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(getBaseContext(),e.toString(),Toast.LENGTH_SHORT).show();
                    }
                });
            }

            @Override
            public void onResponse(okhttp3.Call call, okhttp3.Response response) throws IOException {
                final String resp = response.toString();
                Log.d("changeRes",resp);
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(getBaseContext(),resp,Toast.LENGTH_SHORT).show();
                    }
                });
            }
        });
    }
    private Map changeBody(int flag){
        Map header = new HashMap<>();
        Map body = new HashMap<>();
        Map change = new HashMap<>();

        header.put("mode","ACK");
        header.put("from","/cloud/communion");
        header.put("method","SET");

        if (flag % 2 == 0){
            body.put("value",0);
        }else {
            body.put("value",1);
        }

        flag++;
        this.flag = flag;

        change.put("header",header);
        change.put("body",body);
        return change;
    }

你可能感兴趣的:(安卓okhttp3,retrofit2调用ssl建立post请求(访问华为IoT平台对设备下发命令为例))