Android 实现自签名 HTTPS 教程

本文使用 okhttp 的封装类 okhttp-utils 实现 https 通讯
okhttp-utils 对应 okhttp 版本 3.3.1.

安装

配置 OkhttpClient 和 SSL 证书

在 onCreate 函数中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
InputStream certification = null;
try {
certification = getAssets().open("xxxxx.cer");
} catch (IOException e) {
e.printStackTrace();
}
HttpsUtils.SSLParams sslParams = HttpsUtils.getSslSocketFactory(new InputStream[]{certification}, null, null);
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
})
.sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager)
.build();
OkHttpUtils.initClient(okHttpClient);

其中xxxxx.cer为所连接服务器的证书,可从浏览器导出。
也可以通过OpenSSL工具自签名生成,生成方法详见文章Python Web 框架 - CherryPy

通过 HTTPS 发送 Json 消息

1
2
3
4
5
6
7
8
9
String url = "https://xxxxx";
String json = "{\"key1\":\"value1\", \"key1\":\"value1\"}";
OkHttpUtils
.postString()
.url(url)
.content(json)
.mediaType(MediaType.parse("application/json; charset=utf-8"))
.build()
.execute(new MyStringCallback());

通过 HTTPS 发送同步 POST 请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
new Thread() {
@Override
public void run() {
String url = "https://xxxxx";
Response response;
try {
response = OkHttpUtils
.post()
.url(url)
.addParams("abc", "xxx")
.addParams("def", "yyy")
.build()
.execute();
if (response.isSuccessful()) {
Log.d("OkHTTP","OkHTTP is request success");
} else {
Log.e("OkHTTP", "OkHTTP is request error");
}
String data=response.body().string();
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();

同步的 HTTPS 请求不能再主线程中进行,所以要新建一个线程处理同步请求。

通过 HTTPS 发送异步 POST 请求

1
2
3
4
5
6
7
8
String url = "https://xxxxx";
OkHttpUtils
.post()
.url(url)
.addParams("abc", "xxx")
.addParams("def", "yyy")
.build()
.execute(new MyStringCallback());

Post 表单形式上传文件

1
2
3
4
5
6
7
OkHttpUtils.post()
.addFile("file", "filename", file)
.url(url)
.params(params)
.headers(headers)
.build()
.execute(new MyStringCallback());

支持上传多个文件,addFile 的第一个参数为文件的 key,即类别表单中 <input type="file" name="file"/> 的 name 属性。
params (params) 和 headers (headers) 可以省略。其中 params (params) 为参数格式,类似 addParams ()。

1
2
3
Map<String, String> params = new HashMap<>();
params.put("abc", "xxx");
params.put("def", "yyy");

处理返回消息

新建类 MyStringCallback:

1
2
3
4
5
6
7
8
9
10
11
12
public class MyStringCallback extends StringCallback
{
@Override
public void onError(Call call, Exception e, int id)
{
e.printStackTrace();
}
@Override
public void onResponse(String response, int id) {
Log.i("HTTP", "onResponse:" + response);
}
}