指南
基础
- 安装
- 介绍
- Vue 实例
- 模板语法
- 计算属性和侦听器
- 类和样式绑定
- 条件渲染
- 列表渲染
- 事件处理
- 表单输入绑定
- 组件基础
组件深入
- 组件注册
- Props
- 自定义事件
- 插槽
- 动态和异步组件
- 处理边缘情况
过渡和动画
- 进入/离开和列表过渡
- 状态过渡
可重用性和组合
- 混入
- 自定义指令
- 渲染函数和 JSX
- 插件
- 过滤器
工具
- 单文件组件
- 测试
- TypeScript 支持
- 生产部署
扩展
- 路由
- 状态管理
- 服务器端渲染
- 安全
内部机制
- 深入响应性
迁移
- 从 Vue 1.x 迁移
- 从 Vue Router 0.7.x 迁移
- 从 Vuex 0.6.x 迁移到 1.0
- 迁移到 Vue 2.7
元数据
- 与其他框架的比较
- 加入 Vue.js 社区!
- 认识团队
安全
报告漏洞
当漏洞被报告时,它会立即成为我们的首要关注点,全职贡献者会放下所有工作来处理它。要报告漏洞,请发送电子邮件至 security@vuejs.org。
虽然发现新漏洞的情况很少见,但我们也建议始终使用最新版本的 Vue 及其官方配套库,以确保您的应用程序尽可能安全。
规则 1:绝不使用不可信的模板
使用 Vue 时最基本的安全规则是 **绝不使用不可信的内容作为您的组件模板**。这样做等同于允许在您的应用程序中执行任意 JavaScript 代码 - 更糟糕的是,如果代码在服务器端渲染期间执行,可能会导致服务器被入侵。此类用法的示例
|
Vue 模板被编译成 JavaScript,模板中的表达式将在渲染过程中执行。虽然表达式是针对特定渲染上下文进行评估的,但由于潜在的全局执行环境的复杂性,对于像 Vue 这样的框架来说,在不产生不切实际的性能开销的情况下,完全屏蔽您免受潜在的恶意代码执行是不切实际的。完全避免此类问题的最直接方法是确保您的 Vue 模板的内容始终是可信的,并且完全由您控制。
Vue 为您做了什么
HTML 内容
无论使用模板还是渲染函数,内容都会自动转义。这意味着在这个模板中
|
如果 userProvidedString
包含
|
那么它将被转义为以下 HTML
|
从而防止脚本注入。这种转义是使用原生浏览器 API(如 textContent
)完成的,因此漏洞只能在浏览器本身存在漏洞的情况下才会出现。
属性绑定
类似地,动态属性绑定也会自动转义。这意味着在这个模板中
|
如果 userProvidedString
包含
|
那么它将被转义为以下 HTML
|
从而防止关闭 title
属性以注入新的、任意的 HTML。这种转义是使用原生浏览器 API(如 setAttribute
)完成的,因此漏洞只能在浏览器本身存在漏洞的情况下才会出现。
潜在的危险
在任何 Web 应用程序中,允许未经清理的用户提供的内容作为 HTML、CSS 或 JavaScript 执行都是潜在的危险,因此应尽可能避免。但是,有时一些风险是可以接受的。
例如,像 CodePen 和 JSFiddle 这样的服务允许用户提供的内容被执行,但它是在一个上下文中,在这个上下文中,这是预期的,并且在一定程度上被沙盒化在 iframe 中。在某些情况下,一项重要功能本质上需要一定程度的漏洞,您的团队需要权衡该功能的重要性与漏洞可能带来的最坏情况。
注入 HTML
正如您之前了解到的,Vue 会自动转义 HTML 内容,防止您意外地将可执行的 HTML 注入到您的应用程序中。但是,在您知道 HTML 是安全的情况下,您可以显式地渲染 HTML 内容
使用模板
<div v-html="userProvidedHtml"></div>
使用渲染函数
h('div', {
domProps: {
innerHTML: this.userProvidedHtml
}
})使用带有 JSX 的渲染函数
<div domPropsInnerHTML={this.userProvidedHtml}></div>
请注意,用户提供的 HTML 永远不能被认为是 100% 安全的,除非它位于沙盒化的 iframe 中,或者在应用程序的某个部分,只有编写该 HTML 的用户才能接触到它。此外,允许用户编写自己的 Vue 模板会带来类似的危险。
注入 URL
在这样的 URL 中
|
如果 URL 没有被“清理”以防止使用 javascript:
执行 JavaScript 代码,则存在潜在的安全问题。有一些库,例如 sanitize-url 可以帮助您解决这个问题,但请注意
如果您在前端进行 URL 清理,那么您已经存在安全问题。用户提供的 URL 应该始终由您的后端在保存到数据库之前进行清理。这样,就可以避免所有连接到您的 API 的客户端(包括原生移动应用程序)出现此问题。还要注意,即使使用清理后的 URL,Vue 也无法帮助您保证它们会引导到安全的目的地。
注入样式
看看这个例子
|
假设 sanitizedUrl
已经过清理,因此它绝对是一个真实的 URL,而不是 JavaScript。使用 userProvidedStyles
,恶意用户仍然可以提供 CSS 来进行“点击劫持”,例如,将链接的样式设置为透明框,覆盖“登录”按钮。然后,如果 https://user-controlled-website.com/
被构建成类似于您应用程序的登录页面,那么他们可能已经捕获了用户的真实登录信息。
您可以想象,允许用户为 <style>
元素提供内容会造成更大的漏洞,让该用户完全控制如何对整个页面进行样式设置。这就是为什么 Vue 阻止在模板中渲染样式标签,例如
|
为了让您的用户完全免受点击劫持,我们建议只允许在沙盒化的 iframe 中完全控制 CSS。或者,当通过样式绑定提供用户控制时,我们建议使用其 对象语法,并且只允许用户为他们可以安全控制的特定属性提供值,例如
|
注入 JavaScript
我们强烈建议不要使用 Vue 渲染 <script>
元素,因为模板和渲染函数不应该有副作用。但是,这不是包含在运行时被评估为 JavaScript 的字符串的唯一方法。
每个 HTML 元素都有属性,其值接受 JavaScript 字符串,例如 onclick
、onfocus
和 onmouseenter
。将用户提供的 JavaScript 绑定到这些事件属性中的任何一个都是潜在的安全风险,因此应该避免。
请注意,用户提供的 JavaScript 永远不能被认为是 100% 安全的,除非它位于沙盒化的 iframe 中,或者在应用程序的某个部分,只有编写该 JavaScript 的用户才能接触到它。
有时我们会收到关于如何在 Vue 模板中进行跨站点脚本 (XSS) 的漏洞报告。一般来说,我们不认为这些情况是真正的漏洞,因为没有实际的方法可以保护开发人员免受允许 XSS 的两种情况的影响
开发人员明确要求 Vue 将用户提供的、未经清理的内容作为 Vue 模板进行渲染。这本身是不安全的,Vue 无法知道其来源。
开发人员将 Vue 安装到整个 HTML 页面,该页面恰好包含服务器端渲染的和用户提供的内容。这与 #1 基本上是同一个问题,但有时开发人员可能会在没有意识到的情况下这样做。这会导致可能的漏洞,攻击者提供作为纯 HTML 安全但作为 Vue 模板不安全的 HTML。最佳实践是永远不要将 Vue 安装到可能包含服务器端渲染的和用户提供的内容的节点上。
最佳实践
一般来说,如果你允许未经消毒的用户提供的内容被执行(作为 HTML、JavaScript 甚至 CSS),你可能会让自己面临攻击。无论使用 Vue、其他框架还是根本不使用框架,这条建议都适用。
除了上面针对 潜在危险 的建议外,我们还建议你熟悉以下资源:
然后,利用你学到的知识,检查依赖项的源代码,看看是否存在潜在的危险模式,尤其是那些包含第三方组件或影响 DOM 渲染的依赖项。
后端协调
HTTP 安全漏洞,例如跨站请求伪造 (CSRF/XSRF) 和跨站脚本包含 (XSSI),主要在后端解决,因此不是 Vue 的问题。但是,与后端团队沟通以了解如何最好地与他们的 API 交互仍然是一个好主意,例如,在表单提交时提交 CSRF 令牌。
服务器端渲染 (SSR)
使用 SSR 时,存在一些额外的安全问题,因此请务必遵循 我们的 SSR 文档 中概述的最佳实践,以避免漏洞。