跳到主要内容
版本:v6

安全

清理用户输入

对于诸如 ion-alert 之类的组件,开发者可以允许自定义或用户提供的内容。此内容可以是纯文本或 HTML,应被视为不可信。与任何不可信输入一样,在对它进行任何其他操作之前,务必先进行清理。特别是,使用诸如 innerHTML 而不进行清理,会为恶意行为者提供输入恶意内容的攻击向量,并可能发起跨站脚本攻击 (XSS)

Ionic 为其提供的组件内置了基本的清理实现。但是,它并不是一个全面的解决方案。开发者有责任确保所有传递的数据都经过清理。不同的框架有不同的清理用户输入的解决方案,因此开发者应熟悉其特定框架提供的功能。

对于未使用框架的开发者,或者框架未提供所需清理方法的开发者,我们建议使用 sanitize-html。这个包提供了一个简单的 HTML 清理器,允许开发者指定他们希望在应用中允许的确切标签和属性。

Angular

Angular 内置了 DomSanitizer 类。这有助于通过确保值在 DOM 中使用是安全的来防止 XSS 问题。默认情况下,Angular 会标记任何它认为不安全的值为不安全。例如,以下链接将被 Angular 标记为不安全,因为它会尝试执行一些 JavaScript。

public myUrl: string = 'javascript:alert("oh no!")';

...

<a [href]="myUrl">Click Me!</a>

要了解有关 Angular 提供的内置保护的更多信息,请参阅 Angular 安全指南

React

React DOM 在渲染之前会转义 JSX 中嵌入的值,将它们转换为字符串。例如,以下代码是安全的,因为 name 在渲染之前被转换为字符串:

const name = values.name;
const element = <h1>Hello, {name}!</h1>;

但是,这并不能阻止某人将 JavaScript 注入到诸如锚元素的 href 属性之类的位置。以下代码是不安全的,可能允许 XSS 攻击发生:

const userInput = 'javascript:alert("Oh no!")';
const element = <a href={userInput}>Click Me!</a>;

如果开发者需要实现更全面的清理,他们可以使用 sanitize-html 包。

要了解有关 React 和 JSX 提供的内置保护的更多信息,请参阅 React JSX 文档

Vue

Vue 没有内置任何类型的清理方法。建议开发者使用诸如 sanitize-html 之类的包。

要了解有关绑定到诸如 v-html 等指令的安全建议的更多信息,请参阅 Vue 语法指南

通过 innerHTML 禁用自定义 HTML 解析

ion-alertion-infinite-scroll-contention-loadingion-refresher-contention-toast 接受自定义 HTML 字符串作为某些属性的值。这些字符串使用 innerHTML 添加到 DOM 中,必须由开发者正确清理。开发者可以通过在 IonicConfig 中设置 innerHTMLTemplatesEnabled: false 来禁用此功能。当 innerHTMLTemplatesEnabledfalse 时,传递给受影响组件的值将始终被解释为字符串。

退出内置清理器

对于希望向诸如 ion-toast 等组件添加复杂 HTML 的开发者,他们需要退出 Ionic Framework 内置的清理器。开发者可以全局禁用清理器,也可以逐案绕过它。

备注

绕过清理功能可能会使您的应用容易受到 XSS 攻击。在禁用清理器时,请务必格外小心。

通过配置禁用清理器

Ionic Framework 提供了一个名为 sanitizerEnabled 的应用配置选项,默认设置为 true。将此值设置为 false 以全局禁用 Ionic Framework 的内置清理器。请注意,这不会禁用其他框架(如 Angular)提供的任何清理功能。

逐案绕过清理器

开发者也可以选择在某些场景下退出清理器。Ionic Framework 提供了 IonicSafeString 类来实现这一点。

用法

import { IonicSafeString, ToastController } from '@ionic/angular';

...

constructor(private toastController: ToastController) {}

async presentToast() {
const toast = await this.toastController.create({
message: new IonicSafeString('<ion-button>Hello!</ion-button>'),
duration: 2000
});
toast.present();
}