李氏祖昂 發表於 2025-6-27 09:16:00

Web前端入门第 72 问:JavaScript DOM 内容操作常用方法和 XSS 注入攻击

<p>当项目的安全团队找上门告诉您,您开发的项目存在 XSS 安全漏洞,作为一个开发人员,就问您慌不慌??</p>
<p>HTML 内容写入的时候,如果稍不注意就会触发隐藏 BOSS 漏洞 XSS。</p>
<p>XSS 漏洞原理就是利用了网站上内容输入的地方,比如说常见的评论提交,<code>老六</code> 通过输入评论的地方,提交一些 <code>包含 JS 代码的内容</code> 到服务器,服务器没做任何操作直接写入到数据库,最后在评论查询的时候直接将数据库的内容原样返给前端,而前端拿到此内容的时候,也不做任何处理,直接将内容以 HTML 的形式渲染的页面中,这时候 <code>老六</code> 输入的非法内容就会被当做 JS 代码执行,这就是典型的 XSS 注入攻击。</p>
<p>要避免 XSS 漏洞,就需要对不可信的内容进行过滤;或者<code>不要</code>把这部分内容当做 HTML 处理,直接<code>当做文本</code>渲染也可以避免 XSS 注入。</p>
<h2 id="dom-属性操作">DOM 属性操作</h2>
<p>在了解 DOM 内容操作之前,先学习几个常用的 DOM 属性操作方法,毕竟 JS 与 CSS 联动一般都是通过 DOM 属性进行关联。</p>
<p>比如 JS 控制 class 属性的变化,再在 CSS 中编写不同的 class 样式,就可以让 HTML 元素渲染成不同的样子。</p>
<pre><code class="language-js">// 获取 DOM 属性值
element.getAttribute(name)
// 设置 DOM 属性值,已存在的属性值会被修改
element.setAttribute(name, value)
// 删除 DOM 属性
element.removeAttribute(name)

// 操作 class 方法
element.classList.add(c1, c2, c3, ...) // 添加
element.classList.remove(c1, c2, c3, ...) // 删除
// force 使用布尔值将强制只允许删除或者只允许修改
element.classList.toggle(className, force) // 如果存在则删除,不存在则添加
element.classList.contains(className) // 判断是否存在

// 其他常用属性
element.id // 设置 id
element.className // 设置 class
element.style // 直接设置样式

// 特定标签属性
img.src // 设置图片地址
</code></pre>
<p>通过 <code>className</code> 可直接设置元素的 class 属性,这儿有一个问题,为什么不是直接使用 <code>class</code> 设置呢?</p>
<p>原因是:class 是 JS 中的关键字,为避免引起一些语法问题,所以就换了一个名字 <code>className</code>。</p>
<p>通过 <code>className</code> 控制类名的增删改虽然也不是不能做,但是始终有那么一点点麻烦,所以后来就引入了 <code>classList</code> 用来专门控制 class 属性。</p>
<p>而 <code>Attribute</code> 相关的几个方法,则是可以用来控制元素的所有属性,包括自定义属性和一些默认的属性 id、style、className 等。<strong>所以记住 Attribute 几个方法就已经可以打穿 DOM 属性操作了。</strong></p>
<p>示例:</p>
<pre><code class="language-html">&lt;style&gt;
.red {
    color: red;
}
.blue {
    color: blue;
}
{
    font-weight: bold;
}
{
    font-style: italic;
}
&lt;/style&gt;

&lt;div id="test"&gt;公众号:前端路引&lt;/div&gt;
&lt;img id="img"&gt;

&lt;script&gt;
const test = document.getElementById('test');
const img = document.getElementById('img');

// 设置属性
test.setAttribute('data-type', 'bold')

// 获取属性值
const type = test.getAttribute('data-type')
console.log('🚀 ~ type:', type);

// 移除属性
test.removeAttribute('data-type')

// 添加新的属性
test.setAttribute('data-type', 'italic')

// 判断是否存在Class
const hasRed = test.classList.contains('red')
console.log('🚀 ~ hasRed:', hasRed);

// 添加Class
test.classList.add('red')

// 移除Class
test.classList.remove('red')

// 如果不存在则添加 blue,存在 blue 则移除
test.classList.toggle('blue')


// 给图片设置地址
img.src = 'https://developer.mozilla.org/static/media/firefox.1eabb4da07c095ca04fa.svg'
// 获取图片地址
console.log('🚀 ~ img.src:', img.src);

// 换个 ID 属性
img.id = 'img-1'
// 获取 ID 属性
console.log('🚀 ~ img.id:', img.id);

// 设置图片的 class
img.className = 'img-1'
// 获取图片的 class
console.log('🚀 ~ img.className:', img.className);

// 设置图片边框
img.style.border = '1px solid red'
img.style.borderWidth = '4px'
img.style['border-color'] = 'blue'
// 设置图片宽度
img.style.width = '100px'
// 获取图片的样式
console.log('🚀 ~ img.style:', img.style['border-width']);
&lt;/script&gt;
</code></pre>
<p>在使用 <code>style</code> 属性设置样式的时候,如果使用的是 <code>.</code> 语法赋值,那么必须要改为 <code>小驼峰命名</code>,原因是 JS 中的 <code>.</code> 语法不支持短横线,比如 <code>borderWidth</code>,不能使用 <code>border-width</code>。</p>
<p>在使用数组取值语法的时候,可以直接使用 css 的属性赋值,比如 <code>img.style['border-color'] = 'blue'</code>。</p>
<p>运行结果:</p>
<p><img src="https://img2024.cnblogs.com/blog/596097/202506/596097-20250627091439970-1172099583.png"></p>
<h2 id="dom-内容操作">DOM 内容操作</h2>
<p>DOM 属性操作一般不会触发安全问题, XSS 注入都是发生在 DOM 内容操作的时候,所以在使用 JS 进行 DOM 内容操作时需特别小心。</p>
<p>常用的两个个方法:</p>
<pre><code class="language-js">// 设置 DOM HTML 内容
element.innerHTML = htmlString;
// 设置 DOM 文本内容
element.textContent = textString;
</code></pre>
<p>实例:</p>
<pre><code class="language-html">&lt;div id="test1"&gt;公众号:前端路引&lt;/div&gt;
&lt;div id="test2"&gt;公众号:前端路引&lt;/div&gt;

&lt;script&gt;
const test1 = document.getElementById('test1');
const test2 = document.getElementById('test2');
// 写入 HTML 内容
test1.innerHTML = '&lt;strong&gt;警告&lt;/strong&gt;:用户输入内容';

// 写入文本内容
test2.textContent = '&lt;strong&gt;安全文本&lt;/strong&gt;'; // 直接显示文本,不解析 HTML

// 区别对比
console.log(test2.innerHTML); // 输出: &amp;lt;strong&amp;gt;安全文本&amp;lt;/strong&amp;gt;
console.log(test2.textContent); // 输出: &lt;strong&gt;安全文本&lt;/strong&gt;
&lt;/script&gt;
</code></pre>
<p>运行结果:</p>
<p><img src="https://img2024.cnblogs.com/blog/596097/202506/596097-20250627091431541-1993102433.png"></p>
<h3 id="xss-注入">XSS 注入</h3>
<p>在使用 innerHTML 设置 HTML 内容时,如果用户输入的内容中包含 JS 脚本,那么就会导致 XSS 注入。</p>
<p>比如这样:</p>
<pre><code class="language-html">&lt;div id="test1"&gt;公众号:前端路引&lt;/div&gt;
&lt;div id="test2"&gt;公众号:前端路引&lt;/div&gt;

&lt;script&gt;
const test1 = document.getElementById('test1');
const h1 = `&lt;script&gt;alert("XSS");&lt;\/script&gt;`;
// 直接插入 script 标签被浏览器拦截了,不会引发 XSS 注入
test1.innerHTML = h1;

const test2 = document.getElementById('test2');
// 但可以换一种变体,使用 img 标签也可以做到 XSS 注入
const h2 = `&lt;img src=x onerror="alert('XSS')"&gt;`;
test2.innerHTML = h2;
&lt;/script&gt;
</code></pre>
<p>HTML5 规范规定:通过 innerHTML 动态插入的 <code>&lt;script&gt;</code> 标签不会执行其中的 JavaScript 代码。<br>
这是浏览器的一种安全机制,目的是防止开发者无意或恶意插入可执行脚本。</p>
<p>XSS 注入可能导致的问题:非法用户直接在网站中运行 JS 代码,可以获取用户信息,从而伪造一些请求,达到非法目的。</p>
<h2 id="写在最后">写在最后</h2>
<p>在使用 JS 操作 DOM 内容的时候,需特别防范 XSS 注入问题,尤其是用户输入的内容更加要加强防范,可以把任何用户当做一个潜在的攻击者,他们所有的输入都是不可信的,这样可以避免很多的安全问题。</p>
<p>更多内容参考 MDN:</p>
<p>https://developer.mozilla.org/zh-CN/docs/Web/API/DOMTokenList<br>
https://developer.mozilla.org/zh-CN/docs/Web/API/Element</p>


</div>
<div id="MySignature" role="contentinfo">
    <p>&nbsp;</p>
<p style="font-size: 18px;font-weight: bold;">文章首发于微信公众号【<span style="color:rgb(255, 71, 87)">前端路引</span>】,欢迎 <span style="color:#4ec259">微信扫一扫</span> 查看更多文章。</p>
<p>
<img style="max-width: 320px;" src="https://images.cnblogs.com/cnblogs_com/linx/2447020/o_250228035031_%E5%85%AC%E4%BC%97%E5%8F%B7%E4%BA%8C%E7%BB%B4%E7%A0%81.png"/>
</p>
<p>本文来自博客园,作者:前端路引,转载请注明原文链接:https://www.cnblogs.com/linx/p/18951405</p>
<p>&nbsp;</p><br><br>
来源:https://www.cnblogs.com/linx/p/18951405
頁: [1]
查看完整版本: Web前端入门第 72 问:JavaScript DOM 内容操作常用方法和 XSS 注入攻击