JSONP不是JSON,不能直接json_decode();需用正则提取括号内JSON内容并校验回调函数名,现代场景优先使用CORS+JSON替代JSONP。

JSONP不是JSON,别直接json_decode()
直接对JSONP字符串调用 json_decode() 会返回 null,因为 JSONP 是 JavaScript 函数调用,不是合法 JSON。比如 sug({"q":"淘宝","s":["淘宝网"]}); —— 开头的 sug( 和结尾的 ); 违反 JSON 语法。强行解码不仅失败,还会掩盖真实问题。
用正则提取 JSON 部分,但必须限定边界
核心是剥离回调函数外壳,只保留花括号包裹的有效 JSON 字符串。最稳妥的匹配模式是:
/^[a-zA-Z_][a-zA-Z0-9_]*\s*\(\s*(\{(?:[^{}]|(?R))*\}|$)\s*\)\s*;?$/
但实际项目中没必要写这么复杂。多数 JSONP 响应格式固定,推荐用更保守、可读性高的写法:
详细的 Three.js 3D 图形参考,涵盖场景设置、相机、几何体、材质、光照、动画、控制器、加载器、数学工具和调试。
- 先用
preg_match('/^\w+\((.*)\);?$/', $jsonp, $matches)提取括号内内容 - 检查
$matches[1]是否非空且以{或[开头 - 再用
json_decode($matches[1], true)解析,避免误吞非法字符 - 不要依赖
.*贪婪匹配——遇到嵌套 JSON(如{"data": {"x": 1}})会截断
回调函数名必须校验,否则有 XSS 风险
如果服务端拼接响应时直接把 $_GET['callback'] 插入输出,攻击者可传入 callback=alert(1)// 触发执行。必须严格限制回调名格式:
立即学习“PHP免费学习笔记(深入)”;
- 用
preg_match('/^[a-zA-Z_][a-zA-Z0-9_]*$/', $callback)校验 - 拒绝空值、点号、括号、分号、反斜杠等任意控制或执行字符
- 即使不拼接输出,也要校验——这是 JSONP 协议的基本安全前提
现代场景下优先考虑 CORS + JSON,而非 JSONP
JSONP 是为绕过老式浏览器同源策略设计的,现在主流浏览器都支持 CORS。如果客户端可控(如你自己的前端),直接返回标准 JSON 并配好 Access-Control-Allow-Origin 头,比处理 JSONP 更安全、更易调试。只有当必须兼容 IE8/9 或无法控制客户端时,才值得投入精力写健壮的 JSONP 解析逻辑。


















