
在通过json向javascript传递数据库数据时,若前端使用document.createtextnode()插入内容,则无需在php端提前调用htmlentities();该做法反而会导致html特殊字符被双重编码,破坏原始语义并引发显示异常。
在通过json向javascript传递数据库数据时,若前端使用document.createtextnode()插入内容,则无需在php端提前调用htmlentities();该做法反而会导致html特殊字符被双重编码,破坏原始语义并引发显示异常。
当后端通过json_encode()输出数据、前端通过JSON.parse()接收并使用document.createElement('li')配合createTextNode()动态插入文本时,浏览器会自动将传入的字符串作为纯文本处理,所有HTML标签(如)和特殊字符(如&、)均不会被解析为HTML,而是原样显示——这正是createTextNode()的核心安全机制:它天然具备XSS防护能力,等效于“自动转义”。
因此,以下PHP代码是正确且推荐的做法:
$DB_results = ['Test', '123', '<b>hello</b>', 'B&$B%'];
header('Content-Type: application/json; charset=utf-8');
echo json_encode($DB_results, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
而错误地预先调用htmlentities()会导致数据污染:
// ❌ 错误示例:造成双重编码
$DB_results = [
htmlentities('Test', ENT_QUOTES),
htmlentities('123', ENT_QUOTES),
htmlentities('<b>hello</b>', ENT_QUOTES), // → <b>hello</b>
htmlentities('B&$B%', ENT_QUOTES) // → B&$B%
];
echo json_encode($DB_results); // 输出:["Test","123","<b>hello</b>","B&$B%"]
前端解析后调用createTextNode()时,实际插入的是已编码的字符串,用户将看到<b>hello</b>这样的源码,而非加粗的“hello”。
✅ 正确的前端处理逻辑如下(修正原示例中的语法错误):
// 假设 this.responseText 是合法JSON字符串,如:["Test","123","<b>hello</b>","B&$B%"]
const dbResults = JSON.parse(this.responseText);
const list = document.getElementById('mylist');
dbResults.forEach(str => {
const li = document.createElement('li');
li.appendChild(document.createTextNode(str)); // ✅ 安全:纯文本插入
list.appendChild(li);
});
⚠️ 注意事项:
- json_encode()默认已对控制字符、引号、反斜杠等进行转义,确保JSON格式安全;
- 若需在HTML中直接内联JSON(如<script>var data = <?= json_encode(...) ?>;</script>),应额外设置JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT标志,或使用htmlspecialchars(..., ENT_QUOTES, 'UTF-8')包裹整个JSON字符串,防止闭合攻击;
- 仅当JavaScript使用innerHTML、insertAdjacentHTML()等解析HTML字符串的方式渲染内容时,才需在服务端或客户端对数据做HTML实体编码(如textContent替代innerHTML仍是更优选择)。
总结:信任createTextNode(),避免在JSON序列化前滥用htmlentities();数据应在渲染上下文(而非传输环节)决定是否转义——这是分层防御的关键原则。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











