工作中在使用高德和Mapbox地图,遇到了证书问题,大概错误如下:java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
网上查阅了不少资料,这里整理一下有效的解决方案:
高德地图
在使用这个api方法时候:
fun addMeteorologyLayer(tileUrl: String): TileOverlay {LogUtils.e("tileUrl=$tileUrl")val provider = object : UrlTileProvider(256, 256) {override fun getTileUrl(x: Int, y: Int, zoom: Int): URL {try {var url = tileUrl// 根据瓦片坐标和缩放级别生成对应的 URL 地址url = url.replace("{z}", java.lang.String.valueOf(zoom)).replace("{x}", java.lang.String.valueOf(x)).replace("{y}", java.lang.String.valueOf(y))//Log.i("tileUrl", "getTileUrl: url=$url")return URL(url)} catch (e: MalformedURLException) {e.printStackTrace()}return URL(String.format(tileUrl, x, y, zoom))}}val tileOverlayOptions = TileOverlayOptions().tileProvider(provider).diskCacheEnabled(false).memoryCacheEnabled(true).zIndex(999F)return mAMap.addTileOverlay(tileOverlayOptions)}
由于传进来的tileUrl是自己的公司的地址,https开头,由于证书问题,就会提示文章开头中的错误,解决方案如下:
private fun handleSSLHandshake() {try {val trustAllCerts: Array<TrustManager> = arrayOf(object : X509TrustManager {override fun checkClientTrusted(chain: Array<out X509Certificate>?, authType: String?) = Unitoverride fun checkServerTrusted(chain: Array<out X509Certificate>?, authType: String?) = Unitoverride fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()})val sc: SSLContext = SSLContext.getInstance("TLS")// trustAllCerts信任所有的证书sc.init(null, trustAllCerts, SecureRandom())HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory())HttpsURLConnection.setDefaultHostnameVerifier(object : HostnameVerifier {override fun verify(hostname: String?, session: SSLSession?): Boolean {return true}})} catch (ignored: Exception) {ignored.printStackTrace()}}
Mapbox 地图
在使用下面的api方法时:
fun addWgs84Layer(wgs84title: String) {val tileSet =TileSet.Builder("3.0.0", listOf(wgs84title)).name("Wgs84Layer2").minZoom(0).maxZoom(18).version("2.0.0").scheme(Scheme.XYZ).build()mapboxMap.getStyle { style ->style.addSource(rasterSource("84Layer2") {tileSet(tileSet)tileSize(128L)})style.addLayer(rasterLayer("84Layer2", "84Layer2") {style.getSourceAs<RasterSource>("84Layer2")?.apply {tileNetworkRequestsDelay(0.0)}})}}
由于传进来的tileUrl是自己的公司的地址,https开头,由于证书问题,就会提示文章开头中的错误,解决方案如下:
(1)在res文件夹下新建一个raw 文件夹,将证书xxx_mapbox.der文件放置于此文件夹下。关于证书的获取方法,网上资料很多不在细说。大概是这样:访问你传进来的 tileUrl地址,在浏览器 --》安全–》证书,最后导出你想要的格式即可。
如图:
(2)在res文件夹下新建xml文件夹,并新增一个xml文件用于配置网络安全参数(即额外证书指向),此处我是用的是network_security_config.xml
<network-security-config><base-config cleartextTrafficPermitted="true"><trust-anchors><certificates src="@raw/xxx_mapbox" /><certificates src="system" /></trust-anchors></base-config>
</network-security-config>
(3)最后一步需要在 AndroidMainifest.xml(主配置) 文件中添加 android:networkSecurityConfig ,表示变更网络配置。
这种方式需要定期更换一下证书文件才行,不过一般一年半载不会更换。也尝试过高德地图上面的处理方法但是不行。
总结
至于为什么会出现这种问题,有说是提供的访问的这个url证书不全导致,等等原因吧。目前我也是没有安全搞明白,有知道的小伙伴欢迎留言评论。
参考文章:
Https证书验证相关;security.cert.CertPathValidatorException: Trust anchor for certification path not found.