前端防范 XSS(跨站脚本攻击)

目录

一、防范措施

1.layui util

 核心转义的特殊字符

示例

2.js-xss.js库

安装

1. Node.js 环境(npm/yarn)

2. 浏览器环境

核心 API 基础使用

1. 基础过滤(默认规则)

2. 自定义过滤规则

(1)允许特定标签

(2)允许特定属性

(3)自定义标签处理

(4)自定义属性处理

(5)转义特定字符

常见场景示例

1. 过滤用户输入的评论内容

2. 允许特定富文本标签(如富文本编辑器内容)

注意事项

更多配置


XSS(跨站脚本攻击)是一种常见的网络攻击手段,它允许攻击者将恶意脚本注入到其他用户的浏览器中。XSS攻击通常发生在用户浏览网页时,攻击者通过在网站表单、评论区、URL参数等地方插入恶意脚本代码,当其他用户访问该页面时,这些脚本就会在用户的浏览器中执行。那该如何预防呢,一般是对输入框输入的内容数据进行验证和清理,确保不包含任何可执行的脚本代码。

一、防范措施

可自行封装一个防范XSS攻击的方法,这种较为自由,能根据项目需求自定义防范标准,当然也可以借用相关的工具库,更加方便,下面我为大家整理了相关工具的用法。

1.layui util

layui Util 提供的 layui.util.escape() 是核心的 XSS 防护方法,其核心作用是对 HTML 中的特殊字符进行转义处理,会将具有潜在危险的特殊字符转换为对应的 HTML 实体,从而阻止恶意脚本被浏览器解析执行,从根源上防范大部分反射型、存储型 XSS 攻击。

 核心转义的特殊字符

该方法会针对性转义 HTML 中最具危险性的特殊字符,核心转义规则如下:

原始特殊字符转义后的 HTML 实体说明
<&lt;小于号,HTML 标签开始标识
>&gt;大于号,HTML 标签结束标识
"&quot;双引号,属性值包裹标识
'&#39;单引号,属性值包裹标识
&&amp;和号,HTML 实体的起始标识

这些字符是构建 HTML 标签、属性的关键,恶意攻击者常通过注入包含这些字符的脚本(如 <script>alert('XSS')</script>)来实施攻击,转义后这些脚本会变成纯文本,无法被浏览器解析执行。

示例
layui.use('util', function(){ var util = layui.util; // 模拟用户输入的恶意内容(含XSS脚本) var maliciousContent = '<script>alert("XSS攻击");</script><a href="javascript:evil()">恶意链接</a>'; // 使用escape方法进行XSS转义 var safeContent = util.escape(maliciousContent); // 输出结果(已转为安全的HTML实体) console.log(safeContent); // 输出:&lt;script&gt;alert(&quot;XSS攻击&quot;);&lt;/script&gt;&lt;a href=&quot;javascript:evil()&quot;&gt;恶意链接&lt;/a&gt; // 将转义后的内容插入页面(仅显示为纯文本,不会执行脚本) document.getElementById('content').innerText = safeContent; });

2.js-xss.js库

js-xss 是一个用于防范 XSS(跨站脚本攻击)的 JavaScript 库,能够过滤 HTML 字符串、移除危险标签 / 属性,确保输出的 HTML 安全可渲染。以下是 js-xss 的详细用法,包括安装、基础使用、自定义规则、常见场景等。

安装
1. Node.js 环境(npm/yarn)
# npm npm install xss --save # yarn yarn add xss 
2. 浏览器环境

直接引入 CDN 或本地文件:

<!-- CDN --> <script src="https://cdn.jsdelivr.net/npm/xss/dist/xss.min.js"></script> <!-- 本地(下载后) --> <script src="path/to/xss.min.js"></script> 
核心 API 基础使用

js-xss 的核心是 xss() 函数,传入需要过滤的字符串,返回安全的 HTML。

1. 基础过滤(默认规则)

默认规则会移除所有危险标签(如 <script><iframe>)和危险属性(如 onclickonload),保留常规标签(如 <div><p>)。

// Node.js 环境 const xss = require('xss'); // 浏览器环境直接使用全局变量 xss // 待过滤的危险字符串 const dangerousHtml = ` <div onclick="alert('xss')">点击我</div> <script>stealData()</script> <img src="x" onerror="alert(1)"> `; // 过滤 const safeHtml = xss(dangerousHtml); console.log(safeHtml); // 输出(危险内容被移除): // <div>点击我</div> // <img src="x"> 
2. 自定义过滤规则

通过配置选项自定义规则,满足个性化需求(如允许特定标签 / 属性、自定义标签处理逻辑)。

(1)允许特定标签
const safeHtml = xss(dangerousHtml, { // 白名单:仅允许 div、p、img 标签(默认白名单包含大部分常规标签) whiteList: { div: [], // [] 表示允许该标签,但不允许任何属性 p: ['class'], // 允许 p 标签的 class 属性 img: ['src', 'alt'] // 允许 img 标签的 src、alt 属性 } }); 
(2)允许特定属性
const html = '<div onclick="alert(1)">内容</div>'; const safeHtml = xss(html, { whiteList: { div: ['class', 'data-id'] // 允许 div 的 class 和 data-id 属性,移除 onclick } }); console.log(safeHtml); // 输出:<div>内容</div> 
(3)自定义标签处理

通过 onTag 钩子自定义标签的过滤逻辑:

const safeHtml = xss(dangerousHtml, { onTag: function(tag, html, options) { // 禁止所有 h1 标签,直接返回空 if (tag === 'h1') return ''; // 其他标签按默认规则处理 return undefined; } }); 
(4)自定义属性处理

通过 onTagAttr 钩子自定义属性的过滤逻辑:

const html = '<a href="javascript:alert(1)">链接</a>'; const safeHtml = xss(html, { onTagAttr: function(tag, name, value, isWhiteAttr) { // 处理 a 标签的 href 属性,过滤 javascript: 伪协议 if (tag === 'a' && name === 'href') { if (value.startsWith('javascript:')) { return 'href="#invalid"'; // 替换为无效链接 } } // 其他属性按默认规则处理 return isWhiteAttr ? `${name}="${xss.escapeAttrValue(value)}"` : ''; } }); console.log(safeHtml); // 输出:<a href="#invalid">链接</a> 
(5)转义特定字符

默认会转义 <>&"' 等字符,也可自定义转义规则:

const safeHtml = xss('<p>hello & world</p>', { escapeHtml: function(html) { // 自定义转义:仅转义 & 和 < return html.replace(/&/g, '&amp;').replace(/</g, '&lt;'); } }); console.log(safeHtml); // 输出:<p>hello &amp; world</p> 
常见场景示例
1. 过滤用户输入的评论内容
// 假设用户提交的评论包含危险代码 const userComment = ` <p>我的评论</p> <script>偷取cookie</script> <img src=x onerror="alert('xss')"> `; // 过滤后渲染 const safeComment = xss(userComment, { whiteList: { p: ['class'], img: ['src', 'alt'] // 仅允许 img 的 src 和 alt 属性 } }); // 插入到页面 document.getElementById('comment').innerHTML = safeComment; 
2. 允许特定富文本标签(如富文本编辑器内容)
// 富文本允许的标签和属性 const richTextWhiteList = { h1: ['class'], h2: ['class'], p: ['class', 'style'], a: ['href', 'target', 'class'], img: ['src', 'alt', 'class', 'width', 'height'], strong: [], em: [] }; const richText = '<p>富文本内容<a href="javascript:alert(1)">危险链接</a></p>'; const safeRichText = xss(richText, { whiteList: richTextWhiteList, // 允许 style 属性的特定值(需配合 onTagAttr 过滤) onTagAttr: function(tag, name, value) { if (tag === 'p' && name === 'style') { // 仅允许 color 样式 if (/^color:\s*[a-zA-Z0-9#]+;?$/.test(value)) { return `style="${value}"`; } return ''; } if (tag === 'a' && name === 'href') { // 过滤 a 标签的 javascript: 伪协议 if (value.startsWith('javascript:')) { return 'href="#"'; } return `href="${value}"`; } return `${name}="${value}"`; } }); 
注意事项
  1. 不要完全依赖默认规则:根据业务场景自定义白名单,避免允许不必要的标签 / 属性。
  2. 富文本处理需谨慎:富文本编辑器可能允许更多标签,需精细化配置白名单和属性过滤。
  3. 服务端 + 客户端双重过滤:客户端过滤提升用户体验,服务端过滤是最后一道防线(防止绕过客户端过滤)。
  4. 特殊场景例外:如果需要允许部分安全的脚本(如第三方插件),需通过严格的白名单和校验,避免直接放行。
更多配置

js-xss 的完整配置项可参考官方文档:js-xss,核心配置包括:

  • whiteList:标签白名单(默认值参考源码)。
  • onTag:标签处理钩子。
  • onTagAttr:属性处理钩子。
  • onIgnoreTag:忽略标签时的钩子。
  • onIgnoreTagAttr:忽略属性时的钩子。
  • escapeHtml:自定义转义函数。
  • safeAttrValue:是否过滤属性值中的危险内容。

通过灵活配置,js-xss 可适配绝大多数 XSS 防护场景,是前端 / Node.js 中防范 XSS 的较为推荐的工具之一。

前端虽有xss防护,但是主要还需有后端的一起配合,

不要仅依赖「前端过滤」:攻击者可通过 Postman 等工具直接请求接口,后端必须过滤。

Read more

C++之基于正倒排索引的Boost搜索引擎项目日志+server代码及详解

C++之基于正倒排索引的Boost搜索引擎项目日志+server代码及详解

首先为了更好的查看自己的项目状况,日志是我们做项目可以说必须要写的一部分。而server部分我们可以理解为写了这么多的类就是为了在这里使用。 1. 日志 __FILE__和__LINE__是 C/C++ 编译器预定义的特殊宏: __FILE__: 它会被编译器自动替换为当前代码所在源文件的路径或文件名(字符串类型)。 在日志函数中,它的作用是记录 “这条日志是从哪个文件输出的”。 例如:如果在 test.cpp 中调用 LOG1 宏,__FILE__ 就会被替换为 "test.cpp"(具体可能包含路径,取决于编译器),最终日志中会显示 [test.cpp : ...]。 __LINE__: 它会被编译器自动替换为当前代码所在的行号(整数类型)。 在日志函数中,它的作用是记录 “这条日志是从文件的哪一行输出的”。 例如:如果 LOG1 宏调用写在 test.cpp 的第 25

By Ne0inhk
【问题反馈】JNI 开发:为什么 C++ 在 Debug 正常,Release 却返回 NaN?

【问题反馈】JNI 开发:为什么 C++ 在 Debug 正常,Release 却返回 NaN?

摘要: 在 Android NDK / JNI 开发中,经常会遇到这样一种“诡异”问题:Debug 模式下运行完全正常,而 Release 模式却出现 NaN、Infinity 甚至随机结果。 本文通过一次真实的 JNI 坐标转换案例,深入分析了该问题的根本原因——C++ 返回局部栈内存指针所导致的未定义行为(Undefined Behavior)。 【问题反馈】JNI 开发:为什么 C++ 在 Debug 正常,Release 却返回 NaN? 本文为以下问题的解决记录。由于问题较为典型,故梳理备忘。 https://github.com/eqgis/Sceneform-EQR/discussions/16 一、问题现象描述 1. 现象

By Ne0inhk
【C++初阶】:C++入门相关知识(3):引用 & inline内联函数 & nullptr相关概念

【C++初阶】:C++入门相关知识(3):引用 & inline内联函数 & nullptr相关概念

🎈主页传送门:良木生香 🔥个人专栏:《C语言》 《数据结构-初阶》 《程序设计》《鼠鼠的C++学习之路》 🌟人为善,福随未至,祸已远行;人为恶,祸虽未至,福已远离 前言:在上一篇文章中,我们学习了C++的输入输出,缺省参数以及函数重载,这些都是C++入门必备的基础知识,那么在这篇文章中,我们就要来学习剩下C++其他的基础知识,那就是引用、inline、以及nullptr这些知识。 一、引用 1.1、引用的概念和定义 引用不是定义一个新变量,而是给已经存在的变量起一个别名,那么编译器就不会为别名重新开辟空间,它和引用变量共同使用同一块空间。就好比我们把土豆称为马铃薯,番茄称为西红柿一样,都是取了一个新的别名,但是东西是同一个东西,所以引用的语法如下: 类型& 别名 = 变量 使用方法如下: int a = 10; int&

By Ne0inhk
华为OD技术面八股文_C++_01

华为OD技术面八股文_C++_01

文章目录 * C语言和C++的区别 * C++11引入哪些新特性 * 什么是面向对象?面向对象的三大特性 * malloc和new的区别 * delete和free的区别 * delete和delete[]的区别 * 什么是虚函数?什么是纯虚函数 * 什么是虚函数表?什么是虚函数指针? * 介绍一下虚函数实现机制 * 构造函数和构析函数能不能写为虚函数,为什么 * 说一下构造、析构函数的调用顺序 C语言和C++的区别 1. C++有新增的关键字和语法,还允许自定义命名空间。 2. C++新增类的概念,C语言中只有struct的概念。C++中添加访问权限概念,struct 的默认访问权限和继承权限都是 public,但是 class 的默认访问权限和默认继承权限都是 private. 3. C++引入了类、封装、继承、多态、模板、重载、异常处理机制等特性。而C没有 4.

By Ne0inhk