token-cors
本文回答:请求 403 / 401 / CORS —— token 配置错、无权限、前置代理丢了跨域头。
一、症状
403 Forbidden(token 问题看这里)
GET https://vjmap.com/server/api/v1/map/openmap/xxx 403 (Forbidden)
// body: {"code":7,"data":{"reload":true},"msg":"Token is invalid"}
token 缺失/无效/过期都由网关 JWT 中间件返回 403(msg 为 Token is invalid / Token expired 等),不是 401。
401 Unauthorized
GET .../map/openmap/xxx 401 (Unauthorized)
vjmap 服务只在服务未激活授权 / 超出最大用户数时返回 401(body {error:...}),与 token 无关。
CORS blocked
Access to fetch at 'https://xxx.com/api/...' from origin 'https://yyy.com'
has been blocked by CORS policy
二、token 错误(403,body.code=7)
原因
- token 未设
- token 过期
- token 对应的账号没权限
- 前端硬编码 token(被泄漏后封禁)
排查
const svc = new vjmap.Service(
'https://vjmap.com/server/api/v1/', // url
'xxxxxxx' // token
);
Node 环境(自定义 IRequest)的 403 陷阱
浏览器版 Service 内部用 XMLHttpRequest,且 token 走 args.headers.token 请求头,不在 query 参数里。在 Node 里测 SDK 纯接口时必须:① globalThis.window = globalThis(UMD 顶层引用 window);② 注入 fetch 版 IRequest(new Service(url, token, req) 第三参),且必须转发 args.headers,否则所有请求静默 403 {code:7, msg:"Token is invalid"}、SDK 层只看到 {reload:true}:
globalThis.window = globalThis;
const req = {
get: async (url, params, args) => {
const u = new URL(url);
for (const [k, v] of Object.entries(params ?? {})) u.searchParams.set(k, v);
const r = await fetch(u, { headers: args?.headers }); // ← token 在这里
const t = await r.text();
try { return JSON.parse(t); } catch { return t; }
},
post: async (url, data, args) => {
const r = await fetch(url, { method: "POST", headers: args?.headers, body: JSON.stringify(data) });
return r.json();
},
put: async () => ({}), patch: async () => ({}), del: async () => ({}), options: async () => ({}),
};
const svc = new vjmap.Service(url, token, req); // 第三参注入
排查特征:SDK 返回 {reload: true} 但 currentMapParam() 里 bounds/version 全是 null → 多半是所有请求都在 403。
三、403 权限不足(body 为 {error:"no permission to access this map…"})
原因
- token 账号没有该地图的访问权限
- 密码图没带 secretKey/accessKey(
openMap是 HTTP 200 +{status:403, error}带内返回;其他命令是 HTTP 403) - 地图被设为"仅自己可见"
- 共享过期
排查
- 登录 vjmap 后台 → 我的地图 → 找到对应 mapid
- 看"访问权限"设置
- 或用管理员 token 测试:能行 → 是权限问题
四、CORS 错误
原因
- 前端域名
https://app.com请求后端https://api.other.com,且中间某层没带Access-Control-Allow-Origin - vjmap 服务(官方与自建)默认已放行
*:地图服务每个响应都带Access-Control-Allow-Origin: *,/api/v1/service组走 cors 中间件(AllowOrigins*)——没有 CORS 配置项可开关 - 所以自建部署出现 CORS 报错,多是前置 Nginx/网关未透传、改写了头,或 OPTIONS 预检被拦
前置 Nginx 时补头
如果前置代理吞了上游的跨域头,在 Nginx 反向代理加头:
add_header Access-Control-Allow-Origin $http_origin;
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers 'Content-Type, Authorization, token'; # SDK 用 token 请求头
if ($request_method = OPTIONS) {
return 204;
}
前端代理(开发)
Vite vite.config.js:
export default {
server: {
proxy: {
'/vjmap-api': {
target: 'https://vjmap.com',
changeOrigin: true,
rewrite: p => p.replace(/^\/vjmap-api/, '/server/api/v1')
}
}
}
};
const svc = new vjmap.Service('/vjmap-api/', token); // 走代理,绕 CORS
五、混合内容(Mixed Content)
Blocked loading mixed active content
原因
- 前端 HTTPS 页面调 HTTP 后端 → 被浏览器拦
修法
- 后端升级 HTTPS
- 或前端也用 HTTP(仅测试用)
- 或配置
Content-Security-Policy: upgrade-insecure-requests
六、WebSocket 握手失败
vjmap 某些后端特性走 WebSocket:
WebSocket connection to 'wss://...' failed
原因:
- 后端未开 WSS
- Nginx 未代理
Upgrade头
Nginx:
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
七、CORS 的 preflight
浏览器对 PUT / DELETE 或带自定义 header 的请求先发 OPTIONS:
Access-Control-Allow-Headers: Authorization, Content-Type
后端必须响应 OPTIONS 并返回允许的头。
八、排查一步到位
try {
const res = await svc.openMap({ mapid: 'xxx' });
console.log(res);
if (res.error) console.error('业务错误(HTTP 200 带内):', res.error);
} catch (err) {
// SDK 走 XMLHttpRequest:非 2xx 一律 reject,err = {status, response, data, xhr}(不是 Error/TypeError)
// err.status === 0 → CORS / 网络 / URL 错
// err.status === 403 → JSON.parse(err.response).msg 为 "Token is invalid" 等 → token 问题;.error 为 no permission → 权限
// err.status === 404 → 图不存在;500 → 后端问题
console.error('请求失败:', err.status, err.response);
}
结合 Network 面板看响应头:
Access-Control-Allow-Origin: *存在 → CORS OK- 403 +
{code:7}→ token 问题;403 +{error:"no permission…"}→ 权限 - 401 → 服务未激活 / 超最大用户数
- 500 → 后端问题
九、自建后端的常见配置缺失
| 缺 | 症状 | 修 |
|---|---|---|
Access-Control-Allow-Origin |
CORS blocked | Nginx / 后端加 |
Authorization 头未放行 |
preflight 失败 | Access-Control-Allow-Headers: Authorization |
| HTTPS 证书 | 混合内容 | 证书升级 |
| WebSocket 升级头 | 实时查询失败 | Nginx upgrade 配置 |
十、常见坑
- 前端写死 token 上 git:泄露后被封;改用后端签发。
- token 有尾部空格:复制粘贴时带上了 → 403
Token is invalid;trim 一下。 - URL 末尾
/无需手工处理:new vjmap.Service(url)会自动补末尾/。 - Cookie 鉴权 + CORS 不带 credentials:设
credentials: 'include'+ 后端Access-Control-Allow-Credentials: true。 - IP 白名单限制:开发环境 IP 变了被拒;后台加白名单或用 token。
相关
- 安装 → setup/install
- Service → backend/service-basics
- 打开图 → open-map/open-dwg