大家好,又见面了,我是全栈君。
Https证书
现在网络安全越来越受重视,通用做法是采用https加密通信,使用https需要数字证书,只有合法的证书才能被浏览器、操作系统默认支持,而所谓的合法证书是在CA公司那购买的(原来我们的合法性是花钱从别人那买来的,不得不吐槽这种互联网安全设计真是坑爹),虽然现在也有一些免费CA证书,但申请还是挺麻烦,这里我们使用自己生成的https证书。
服务端使用https
生成https证书
JDK自带的keytool工具可以很方便生成https证书,可以查看它的使用方法:
比如这条命令就可以生成一个有效期10年的证书:
keytool -genkey -alias spring -validity 3560 -keystore spring.keystore复制代码
服务端配置https证书
服务端一般使用Tomcat、Jetty、Undertow等作为Servlet容器,我们将上面生成的keystore证书放在项目中,然后在配置文件中引入证书即可:
server.ssl.key-store=spring.keystore
server.ssl.key-alias=spring
server.ssl.key-password=password
server.ssl.key-store-type=JKS复制代码
这样服务端就支持https了,启动项目访问服务就要加https前缀,如 https://localhost:8080/user
Android自定义https校验
如果是花钱买的CA证书是不需要额外配置的,Android系统内部有信任列表,会自行校验通过,这里讲配置自定义https校验。
Android端通常使用 Retrofit 做网络请求,Retrofit底层就是OKhttp,OKhttp实现自定义https校验并不难,主要分三步。
把证书公钥预埋在APP中
这条命令可以导出证书公钥字符串:
keytool -list -rfc -keystore tomcat.keystore复制代码
把这个公钥作为一个字符串常量放在项目中供后面校验使用。
自定义证书校验逻辑
使用上面的公钥字符串构建X509TrustManager对象,在checkServerTrusted方法中校验服务端证书:
X509TrustManager trustManager = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
//校验客户端证书
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
//校验服务端证书
X509Certificate ca = (X509Certificate) CertificateFactory.getInstance("X.509")
.generateCertificate(new ByteArrayInputStream(PUB_KEY.getBytes()));
for (X509Certificate cert : chain) {
// 检查服务端证书是否过期
cert.checkValidity();
try {
//和APP预埋证书对比
cert.verify(ca.getPublicKey());
} catch (Exception e) {
//证书校验异常
throw new SecurityException("证书错误!");
}
}
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
};复制代码
注意证书校验异常时抛出一个SecurityException,如果不抛出这个RuntimeException,程序会继续执行,请求依然正常,证书校验就没有意义。
设置OkHttpClient校验证书
然后使用上面的trustManager构建OkHttpClient
SSLSocketFactory sslSocketFactory = null;
try {
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[]{trustManager}, new SecureRandom());
sslSocketFactory = sslContext.getSocketFactory();
} catch (NoSuchAlgorithmException | KeyManagementException e) {
e.printStackTrace();
}
final HostnameVerifier hostnameVerifier = new HostnameVerifier() {
@Override
public boolean verify(final String hostname, final SSLSession session) {
//服务端主机域名地址校验
return true;
}
};
OkHttpClient client = new OkHttpClient.Builder()
.hostnameVerifier(hostnameVerifier)
.sslSocketFactory(sslSocketFactory, trustManager)
.build();复制代码
使用这个配置好的OkHttpClient与服务端交互,就可以支持自定义https证书加密通信了,如果服务端证书不符,请求会自动断开。
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/108148.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...