Node系列 · Express:跨域之 JSONP
Node系列 · Express跨域之 JSONPJSONP 是 CORS 之前的老式跨域方案——利用script标签不受同源策略限制的特性。本章讲清楚 JSONP 的工作原理、Express 实现、以及它为什么被 CORS 取代。一、同源策略与跨域1.1 同源页面源http://a.com/page.html 接口源http://b.com/api/users判定标准协议 域名 端口都相同才算同源。例子是否同源http://a.com/x→http://a.com/y✅http://a.com/x→https://a.com/x❌协议不同http://a.com/x→http://b.com/x❌域名不同http://a.com/x→http://a.com:8080/x❌端口不同1.2 浏览器不允许非同源请求浏览器主动拦截XMLHttpRequest/fetch跨域响应——但img/script/link等标签不受同源限制。JSONP 利用的就是script的特权。二、JSONP 原理服务器 b.com浏览器 a.com服务器 b.com浏览器 a.com把响应当 JS 执行调用 fn 函数GET /api/users?callbackfnfn([{id:1}, {id:2}])客户端定义全局函数window.fn动态创建script srchttp://b.com/api?callbackfn服务端把数据包在 fn 调用里返回fn([...])浏览器把响应当 JS 执行调用fn函数客户端拿到数据2.1 客户端代码script function handleUsers(users) { console.log(拿到数据:, users); } /script !-- 动态加载 script -- script srchttp://b.com/api/users?callbackhandleUsers/script2.2 服务端代码Expressapp.get(/api/users, (req, res) { const users [{ id: 1, name: Alice }, { id: 2, name: Bob }]; const callback req.query.callback; if (callback) { // JSONP 模式把数据包在函数调用里 res.type(application/javascript); res.send(${callback}(${JSON.stringify(users)})); } else { // 普通 JSON 模式 res.json(users); } });响应内容handleUsers([{id:1,name:Alice},{id:2,name:Bob}])浏览器执行这段 JS → 调用handleUsers→ 客户端拿到数据。三、JSONP 的致命缺陷3.1 只能 GETscript标签天然只支持 GET 请求——POST / PUT / DELETE 没法做。3.2 难调试服务端返回的是 JS 代码而非 JSON——浏览器 Network 面板看不到结构化响应只能看到一段 JS 字符串。3.3 安全风险// 服务端可以执行客户端传来的 callback 函数名 const callback req.query.callback; res.send(${callback}(${data})); // 如果 callback alert(1);evil() // 服务端返回alert(1);evil({...}) // 浏览器执行alert(1) 调用 evil 函数::: dangerJSONP 存在反射型 XSS 风险——callback参数如果不过滤就被攻击者利用// ✅ 正确限制 callback 只能是合法标识符 const callback req.query.callback; if (!/^[a-zA-Z_$][\w$]*$/.test(callback)) { return res.status(400).json({ error: invalid callback }); } res.send(${callback}(${JSON.stringify(data)}));必须严格校验 callback——只允许字母数字下划线。:::3.4 错误处理难JSONP 失败只能靠超时——没有 HTTP 状态码没有错误信息。四、被 CORS 取代CORSCross-Origin Resource Sharing是 W3C 推荐的现代方案维度JSONPCORSHTTP 方法仅 GET任意错误处理HTTP 状态码标准安全callback 注入风险受控 Origin 白名单调试难标准 HTTP 响应浏览器支持所有浏览器所有现代浏览器::: tip新项目不要用 JSONP。CORS 是更现代、更安全的方案详见 cors 中间件 章节。:::五、历史场景JSONP 只在以下场景还有价值调用 IE8/IE9 的老接口不支持 CORS调用只暴露 JSONP 的第三方接口无法让对方改否则一律用 CORS。六、最佳实践场景推荐新项目跨域CORS详见 跨域 CORS 与 cors 中间件维护老 JSONP 接口必须严格过滤 callback 参数客户端调用优先用fetch/axios CORS不要再造 JSONP 轮子服务端 JSONPcallback强校验只允许合法标识符七、小结JSONP 利用script标签不受同源策略限制的特性客户端定义 callback 函数 → 服务端把数据包在 callback 调用里返回致命缺陷仅 GET / 难调试 / callback 注入风险 / 错误处理难新项目用 CORS不要用 JSONP维护 JSONP 接口时严格过滤 callback只允许合法标识符防 XSS
上一篇/下一篇内容由系统自动关联
返回资讯列表 →