You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从安全漏洞角度寻求JavaScript中innerHTML的替代方案

替代innerHTML的安全方案

从安全角度看,innerHTML的核心风险是会解析并执行传入的HTML内容,若change_obj中的数据包含用户可控的恶意代码,极易引发XSS攻击。以下是几种更安全且比手动逐个创建元素更简洁的替代方案:

原问题代码示例

存在风险的innerHTML实现

td.innerHTML = "<b>"+change_obj["old_end_cust_id"]+"</b>," + "<br>" + change_obj["old_address"].join(",<br>")

可行但繁琐的原生DOM创建方案

var parentDivTag11 =  document.createElement("div");
var parentBoldTag11 = document.createElement("b");
parentBoldTag11.textContent = change_obj["old_end_cust_id"]+",";
parentDivTag11.appendChild(parentBoldTag11);

for (let i = 0; i < change_obj["old_address"]?.length; i++) {
    var divTag11 = document.createElement("div");
    divTag11.textContent=change_obj["old_address"][i]+",";
    parentDivTag11.append(divTag11);
}

td.appendChild(parentDivTag11);

更简洁的安全替代方案

方案1:文本转义+insertAdjacentHTML

先将用户输入内容转义为HTML实体,再拼接可信的HTML结构,最后用insertAdjacentHTML插入(仅确保HTML结构可信时使用,用户内容必须先转义):

// 简单HTML转义函数
function escapeHtml(text) {
    return text.replace(/[&<>"']/g, char => {
        const entities = {
            '&': '&amp;',
            '<': '&lt;',
            '>': '&gt;',
            '"': '&quot;',
            "'": '&#039;'
        };
        return entities[char];
    });
}

const escapedId = escapeHtml(change_obj["old_end_cust_id"]);
const escapedAddresses = change_obj["old_address"].map(addr => escapeHtml(addr)).join("<br>");

td.insertAdjacentHTML('beforeend', `<b>${escapedId},</b><br>${escapedAddresses}`);

方案2:DocumentFragment简化DOM创建

通过文档片段一次性插入所有元素,减少DOM重绘,同时简化代码:

const fragment = document.createDocumentFragment();

// 创建加粗ID元素
const boldId = document.createElement("b");
boldId.textContent = `${change_obj["old_end_cust_id"]},`;
fragment.appendChild(boldId);
fragment.appendChild(document.createElement("br"));

// 批量添加地址元素
change_obj["old_address"]?.forEach(addr => {
    const addrEl = document.createElement("span");
    addrEl.textContent = `${addr},`;
    fragment.appendChild(addrEl);
    fragment.appendChild(document.createElement("br"));
});

// 移除最后多余的<br>
if (fragment.lastChild?.tagName === "BR") {
    fragment.removeChild(fragment.lastChild);
}

td.appendChild(fragment);

方案3:使用<template>元素

利用模板元素的内容克隆能力,兼顾结构可读性与文本安全性:

// 创建模板
const template = document.createElement("template");
template.innerHTML = `<b></b><br>`;

// 克隆模板内容
const content = template.content.cloneNode(true);
// 设置ID文本(textContent自动转义)
content.querySelector("b").textContent = `${change_obj["old_end_cust_id"]},`;

// 添加地址元素
change_obj["old_address"]?.forEach(addr => {
    const addrEl = document.createElement("span");
    addrEl.textContent = `${addr},`;
    content.appendChild(addrEl);
    content.appendChild(document.createElement("br"));
});

// 移除最后多余的<br>
if (content.lastChild?.tagName === "BR") {
    content.removeChild(content.lastChild);
}

td.appendChild(content);

所有方案的核心逻辑都是将用户提供的内容作为纯文本处理,避免HTML解析带来的XSS风险,同时通过代码优化解决手动创建元素的繁琐问题。

内容的提问来源于stack exchange,提问作者ArunKarthick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 06:37:31