为什么Google在JSON中插入while(1);以及如何避免上当:JavaScript开发者的顶级错误
如果你曾经在使用Google API时查看过开发者控制台,或者只是搜索过服务器返回的奇怪响应,那么你肯定注意到过类似这样的内容:
while(1);["some","data"]看起来像一个会挂起浏览器的无限循环,对吧?但实际上,这是一个天才的防护机制。让我们来弄清楚为什么Google在JSON前添加while(1),开发者在处理此类响应时犯了哪些错误,以及如何避免它们。
这个问题是Stack Overflow上最热门的问题之一(有数千次浏览),这并非没有原因。它不仅涉及技术细节,还涉及网络安全的基本原则。
JSON中的while(1);是什么?它从何而来?
让我们从最重要的开始。Google在JSON前添加while(1)不是为了破坏你的代码,而是为了防御一种称为JSON劫持的攻击。
想象一下过去的好时光,当时网站使用顶层JSON数组(例如[{"user":"admin","token":"secret"}])。攻击者可以覆盖全局的Array或Object构造函数,并通过<script>标签窃取数据。浏览器将JSON作为JavaScript执行,数据就泄露了。
Google的解决方案是添加前缀while(1);。这使得JSON成为无效的JavaScript(无限循环会阻止恶意脚本执行),但JSON本身仍然是正确的——只需正确解析它,删除前缀即可。
现在,这种做法已成为许多大型API的安全标准。但如果你不了解它,你的代码可能会出错。
JavaScript开发者在处理受保护的JSON时常见的5个错误
错误#1:直接尝试解析响应
最常见的错误是开发者从服务器获取响应后,直接将其传递给JSON.parse()。结果——解析错误,因为while(1);不是有效的JSON。
fetch('https://api.google.com/some-endpoint') .then(response => response.text()) .then(data => { // 错误!JSON.parse会失败 const parsed = JSON.parse(data); console.log(parsed); }) .catch(err => console.error('解析错误:', err));如何避免:在解析之前始终删除while(1);前缀。
fetch('https://api.google.com/some-endpoint') .then(response => response.text()) .then(data => { // 删除防护前缀 const cleanJson = data.replace(/^\\)?\\s*while\\s*\\(\\s*1\\s*\\)\\s*;\\s*/, ''); const parsed = JSON.parse(cleanJson); console.log(parsed); }) .catch(err => console.error('解析错误:', err));错误#2:使用response.json()而不进行处理
Fetch API中的response.json()方法期望纯JSON。如果服务器返回while(1);...,那么response.json()会抛出异常。开发者通常认为这是API的bug,而不是安全特性。
// 这段代码会因"Unexpected token w"错误而失败fetch('https://api.google.com/endpoint') .then(response => response.json()) // 错误! .then(data => console.log(data));如何避免:使用response.text(),然后手动删除前缀。
fetch('https://api.google.com/endpoint') .then(response => response.text()) .then(text => { const jsonText = text.replace(/^\\)?\\s*while\\s*\\(\\s*1\\s*\\)\\s*;\\s*/, ''); return JSON.parse(jsonText); }) .then(data => console.log(data));