举个例子:
javascript
// 当song中存在英文单引号时,会导致无法正确处理:
p.innerHTML = `<li onclick="clicksong('${song}')">${song}</li>`;
这是一个典型的XSS漏洞和安全问题。当song
变量包含单引号时,会破坏JavaScript字符串,导致语法错误或安全漏洞。以下是几种改进方案:
方案1:使用数据属性(推荐)
javascript
p.innerHTML = `<li data-song="${escapeHTML(song)}">${escapeHTML(song)}</li>`;
p.querySelector('li').addEventListener('click', function() {
clicksong(this.dataset.song);
});
方案2:使用事件委托
javascript
p.innerHTML = `<li>${escapeHTML(song)}</li>`;
p.querySelector('li').addEventListener('click', () => {
clicksong(song);
});
方案3:如果必须保持内联事件,使用JSON序列化
javascript
p.innerHTML = `<li onclick="clicksong(${JSON.stringify(song)})">${escapeHTML(song)}</li>`;
完整的HTML转义函数
javascript
function escapeHTML(str) {
const div = document.createElement('div');
div.textContent = str;
return div.innerHTML;
}
// 或者使用更全面的转义
function escapeHTML(str) {
return str.replace(/[&<>"']/g, function(match) {
const escape = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
};
return escape[match];
});
}
方案4:使用模板引擎或框架
javascript
// 使用现代JavaScript创建元素
const li = document.createElement('li');
li.textContent = song;
li.addEventListener('click', () => clicksong(song));
p.appendChild(li);
最佳实践示例
javascript
// 安全的歌曲列表渲染函数
function renderSongList(songs, container) {
const fragment = document.createDocumentFragment();
songs.forEach(song => {
const li = document.createElement('li');
li.textContent = song;
li.addEventListener('click', () => clicksong(song));
fragment.appendChild(li);
});
container.innerHTML = ''; // 清空容器
container.appendChild(fragment);
}
关键改进点
- 分离HTML和JavaScript:避免在HTML中嵌入JavaScript代码
- 正确转义:对动态内容进行适当的HTML转义
- 使用事件监听器 :代替内联的
onclick
属性 - 数据属性:安全地存储需要的数据
推荐使用方案1或方案4,它们完全避免了字符串拼接带来的安全问题,代码也更易维护。