1. 背景说明 #
功能需要背景情况说明,为什么要采用无网络环境调用百度地图:
- 某省零工驿站项目,存在部分功能在核心经办网络区,此区域网络无法连接互联网;
- 该项目中新增零工驿站功能在信息录入时,需要在可展示地图上选择地址及坐标点,并将该地址和坐标保存;
- 保存的坐标点需要在互联网下的零工网站中通过地图标注查看、距离计算等操作;
- 本方案采用nginx反向代理方式解决,文档内总结了所需要代理的url地址、修改的js文件,可供实时人员参考使用。
效果图例:

1.1 调用情况分析 #
1、开发人员在开发过程中,直接引用了百度地图api接口(在线模式);
2、由于上线紧急,短时内无法重新修改程序变更为离线加载模式;
3、项目采用网页版调用地图,如使用离线调用方式需要下载地图瓦片,一般需要第三方工具(部分收费);
4、离线地图的实时更新性较差;
5、根据分析采用nginx反向代理方式,根据加载百度地图时所需要访问的资源通过公共服务区代理到互联网方式,从而解决可以实时加载地图的效果;
***PS:***百度地图开发者平台反馈,目前不支持离线调用百度地图接口;
*可采用离线地图可参考此文档:*https://lbs.baidu.com/faq/api?title=androidsdk/guide/create-map/offlinemap
2. 分析排查 #
2.1 工程中引用百度地图作用 #
1、工程引用vue-baidu-map包、分析包内引入的api的地址
通过分析引用包后,发现工程中存在两处重点加载在线百度地图api地址位置;
百度地图api地址:https://api.map.baidu.com/api?v=2.0&ak="+t+"&callback=_initBaiduMap
\node_modules\vue-baidu-map\components\map\Map.vue
图1-1:

\node_modules\vue-baidu-map\index.js
图1-2:

2.2 分析调用百度地图API #
1、通过F12分析加载地图调用的api地址&作用
通过图2-1分析发现加载地图时候并非通过核心服务后端调用,而是通过调用浏览器端加载;也就意味着浏览经办系统的PC机所在网络必须能够具备访问互联网方可正常加载地图,否则即图2-2效果;
图2-1(请求api地址作用):

图2-2(无法正常请求api地址):


2.3 尝试修改配置文件 #
发现修改两处调用api地址,可以改变网页加载时地图调用地址;
因此,初步解决方案按照修改两处配置文件为核心内网访问地址,并通过nginx方向代理方式将地图api连接代理到内网中。
1、修改图1-1、图1-2两处配置,将系统调用的api地址改成 :http://...:8001/baidumapapi/
2、配置nginx服务代理:
server {
listen 8001;
##百度地图API
location /baidumapapi/ {
proxy_pass https://api.map.baidu.com/;
}
}
配置后,通过访问 http://xxx.xxx.xxx.xxx:8001/baidumapapi/ 地址后,通过nginx将转向 https://api.map.baidu.com/ 目标地址。
图2-3(可以正常请求到api,状态码200):

通过F12网络访问发现,成功修改了服务的请求地址,并成功通过nginx转向到目标服务器,状态码:200。
3. 问题解决处理 #
3.1 分析请求api地址与改造 #
3.1.1 api接口分析 #
经过分析,请求 api.map.baidu.com 时候,实际调用地址为:
https://api.map.baidu.com/api?v=2.0&ak=${ak}&callback=_initBaiduMap ${ak} 自己申请的key
图3-1:

获取 核心map.js 将此script引入到工程中(见图3-1)。
图3-2:此处js获取后下载保存

3.1.2 本地化js代码改造 #
1、通过图3-1分析,需要本地化map_init.js,内容如下:
(function () {
window.HOST_TYPE = "2";
window.BMap_loadScriptTime = (new Date).getTime();
window.BMap = window.BMap || {};
window.BMap.apiLoad = function () {
delete window.BMap.apiLoad;
if (typeof _initBaiduMap == "function") {
_initBaiduMap()
}
};
var s = document.createElement('script');
//s.src = 'https://api.map.baidu.com/getscript?v=2.0&ak=AHmzmrYTd8QjQTZSc4Pds2BMUu9R3Kcw&services=&t=20230829140758';
//将上方连接更换为下方本地连接;
s.src = 'http://**.**.***.***:8001/getscript/';
document.body.appendChild(s);
})();
2、经过分析图3-2,本地化map.js,其文件内含有多处调用api地址,需逐一找出后统一替换修改,以下整理了替换的位置:
1、#百度地图key,配置本项目的key
window.BMAP_AUTHENTIC_KEY = "AHmzmrxxxxxxxxxxxxxu9R3Kcw";
2、调用地址:
static.tieba.baidu.com
dlswbr.baidu.com
lbsyun.baidu.com/apiconsole
maponline0.bdimg.com/starpic
maponline1.bdimg.com/starpic
maponline2.bdimg.com/starpic
maponline3.bdimg.com/starpic
api.map.baidu.com
以上调用地址均改成(如图3-4):
10.40.14.124:8001/static.tieba.baidu.com
10.40.14.124:8001/dlswbr.baidu.com
10.40.14.124:8001/lbsyun.baidu.com/apiconsole
10.40.14.124:8001/maponline0.bdimg.com/starpic
10.40.14.124:8001/maponline1.bdimg.com/starpic
10.40.14.124:8001/maponline2.bdimg.com/starpic
10.40.14.124:8001/maponline3.bdimg.com/starpic
图3-3:

根据上述情况,整理本地化js如下:
[root@rst-lgsc--0021 js]# pwd
/opt/nginx/js
[root@rst-lgsc--0021 js]# ll
total 732
-rw-r--r-- 1 root root 355735 Sep 7 18:03 abclite-2063-s.js
-rw-r--r-- 1 root root 565 Sep 6 18:21 map_init.js
-rw-r--r-- 1 root root 386979 Sep 7 18:14 map.js
3.1.3 本项目特殊情况本地化abclite-2063-s.js #
由于本项目访问外部接口之后1个,且公共服务区端口为 ssl协议,因此通过ng代理abclite-2063-s.js文件时会产生调用不到的情况,因此本地化此文件;(ssl协议的端口下配置了其他参数,存在相互影响)
# http://**.**.**.**:8001/dlswbr.baidu.com/abclite-2063-s.js?_t=" + a;
nginx配置:
location /dlswbr.baidu.com/{
#proxy_pass http://**.**.**.**:8001/dlswbr.baidu.com/;
alias /opt/nginx/js/;
index abclite-2063-s.js;
}
里面还包括了以下地址,由于本项目不使用,因此没有配置。
map.baidu.com
mapapip0.bdimg.com、mapapip1.bdimg.com、mapapip2.bdimg.com
apisv0.bdimg.com、apisv1.bdimg.com
gsp0.baidu.com
itsmap2.baidu.com
j.map.baidu.com
webmap0.bdimg.com
3.1.4 修改工程中请求API地址 #
\node_modules\vue-baidu-map\components\map\Map.vue
\node_modules\vue-baidu-map\index.js
将请求 api.map.baidu.com 地址改成:http://**.**.**.**:8001/baidumapapi/
图3-4:


3.2 中间件支持 #
使用nginx 反向代理
配置文件-19.167.x.XX:8001(核心服务网络区)
server {
listen 8001;
##百度地图API
location /baidumapapi/ {
proxy_pass https://22.168.xx.xx:15000/;
}
}
#############################################################
配置文件-22.168.xx.xx:15000(DMZ-公共服务网络区)
server {
listen 15000 ssl;
ssl_protocols TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_certificate ../ssl/xxx.rst.xxxx.gov.cn.crt;
ssl_certificate_key ../ssl/xxx.rst.xxxx.gov.cn.key;
#将所有HTTP请求重定向到HTTPS
error_page 497 301 https://$host:15001$request_uri;
location / {
proxy_pass https://api.map.baidu.com/;
}
经过逐一排查整理后,需要开通的代理地址如下:
##百度地图核心请求
location /api.map.baidu.com/ {
#include /opt/nginx/conf/conf.d/http.proxy;
proxy_pass https://api.map.baidu.com/;
}
##百度地图瓦片服务请求
location /maponline0.bdimg.com/ {
proxy_pass https://maponline0.bdimg.com/;
}
location /maponline1.bdimg.com/ {
proxy_pass https://maponline1.bdimg.com/;
}
location /maponline2.bdimg.com/ {
proxy_pass https://maponline2.bdimg.com/;
}
location /maponline3.bdimg.com/{
proxy_pass https://maponline3.bdimg.com/;
}
##百度地图abclite-2063-s.js请求(可以本地化)
location /dlswbr.baidu.com/{
proxy_pass https://dlswbr.baidu.com/;
#alias /opt/nginx/js/;
#index abclite-2063-s.js;
}
##百度地图定位服务请求
location /lbsyun.baidu.com/{
proxy_pass https://lbsyun.baidu.com/;
}
location /static.tieba.baidu.com/{
proxy_pass https://static.tieba.baidu.com/;
}
本地化文件:
server {
listen 8001;
location / {
alias /opt/nginx/js/;
index map_init.js;
}
location /getscript/ {
alias /opt/nginx/js/;
index map.js;
}
}
3.3 网络环境支持 #
使用该功能PC机所在网络为核心专网,需要访问百度API地址需要互联网区,因此所需网络拓扑如下:
图3-5:

4. 成果展示 #
1、可以正确加载地图;
2、可以正确使用定位功能并获取地图经纬度;

F12网络访问:
