如何编写安全的JavaScript代码以防止XSS攻击?

如何编写安全的JavaScript代码以防止XSS攻击?
最新回答
看轻也就看清

2020-05-08 09:09:38

编写安全的JavaScript代码防止XSS攻击需遵循输入验证、输出转义、使用安全API和HTTP头防护的综合策略,具体措施如下:

一、输入验证与清理
  • 前端与后端双重验证:所有用户输入(如表单、URL参数、API数据)均需在前端和后端验证格式、长度、类型和字符集。例如,邮箱输入仅允许字母、数字、@和.。
  • 白名单机制:通过正则表达式限制输入字符范围,如/^[a-zA-Z0-9@.]+$/过滤邮箱输入,拒绝非法字符。
  • 避免直接使用用户输入:禁止将用户输入直接拼接至SQL查询或命令行参数中,防止命令注入。
二、输出转义与安全API
  • 优先使用textContent替代innerHTML:textContent会自动转义HTML标签(如<转为&lt;),避免脚老慎本执行。例如:const userInput = '<script>alert(1)</script>';element.textContent = userInput; // 显示为文本,不执行脚本
  • HTML净化库辩含信处理动态内容:若必须插入HTML(如富文本编辑器),使用DOMPurify等库净化内容:import DOMPurify from 'dompurify';const dirtyHtml = '<div onclick="alert(1)">User Content</div>';const cleanHtml = DOMPurify.sanitize(dirtyHtml); // 移除恶意标签element.innerHTML = cleanHtml;
  • 上下文相关转义

    HTML内容:转义<、>、&为&lt;、&gt;、&amp;。

    属性值:转义引号("、')和空格,防止闭合标签注入。例如:const userInput = '" onclick="alert(1)"';element.setAttribute('title', userInput.replace(/"/g, '&quot;'));

    JavaScript字符串:拼接脚本时转义引号和换行符,如"、n。

三、利用现代框架的安全特性
  • React

    默认插值({variable})自动转义,但dangerouslySetInnerHTML需谨慎使用,必须配合净化库:function SafeComponent({ html }) { const cleanHtml = DOMPurify.sanitize(html); return <div dangerouslySetInnerHTML={{ __html: cleanHtml }} />;}

  • Vue

    双大括号{{ }}自动转义,携轮v-html指令等同于innerHTML,应避免用于用户内容:<template> <div>{{ userInput }}</div> <!-- 安全 --> <div v-html="sanitizedHtml"></div> <!-- 需提前净化 --></template>

四、启用安全的HTTP头
  • Content-Security-Policy (CSP):通过服务器设置CSP头,限制脚本加载来源,禁止内联脚本:Content-Security-Policy: default-src 'self'; script-src 'self'
    https://trusted.cdn.com
  • HttpOnly Cookie:标记Cookie为HttpOnly,防止通过document.cookie窃取会话信息:Set-Cookie: sessionId=abc123; HttpOnly; Secure
  • 其他安全头

    X-Content-Type-Options: nosniff:阻止浏览器推测响应类型。

    X-XSS-Protection: 1; mode=block(虽已弃用,但旧浏览器仍支持)。

五、全链路安全实践
  • 不依赖客户端验证:客户端验证仅用于提升用户体验,后端必须重新验证所有输入。
  • 定期安全审计:使用工具(如ESLint插件eslint-plugin-security)检测代码中的XSS风险。
  • 最小权限原则:限制前端代码的DOM操作范围,避免全局事件监听器。
示例:完整防护流程// 1. 输入验证(前端示例)function validateEmail(email) { return /^[a-zA-Z0-9@.]+$/.test(email); // 简化版白名单}// 2. 输出转义(纯文本)function escapeHtml(str) { return str.replace(/[&<>'"]/g, (char) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', "'": '&#39;', '"': '&quot;' }[char]));}// 3. 安全插入HTML(结合DOMPurify)import DOMPurify from 'dompurify';const userInput = '<p>User Content</p><script>alert(1)</script>';const cleanHtml = DOMPurify.sanitize(userInput);document.getElementById('output').innerHTML = cleanHtml;// 4. 后端配合(Node.js Express示例)app.use(helmet({ contentSecurityPolicy: { directives: { defaultSrc: ["'self'"] } } }));app.use(cookieParser({ httpOnly: true, secure: true }));

关键点总结:XSS防护需贯穿数据流全生命周期,从输入验证到输出转义,结合框架安全机制和HTTP头加固,形成多层次防御体系。