【问题标题】:Sanitize input in Angular2 [duplicate]清理Angular2中的输入[重复]
【发布时间】:2016-03-31 17:41:48
【问题描述】:

我正在尝试从我的数据库中获取第三方(可能不安全)的 html 内容并将其插入到我的 html 文档中。

我如何安全地做到这一点(防止 XSS)?

Angular1.x 中曾经有 $sce 来清理输入,我该如何在 Angular2 中做到这一点?据我了解,默认情况下 Angular2 会自动对其进行清理,对吗?

这样的事情是行不通的:

<div class="foo">
    {{someBoundValueWithSafeHTML}} // I want HTML from db here
</div>

【问题讨论】:

  • @DanielGartmann 我确实确实想清理内容。既然您指出了这一点,我对自己的措辞感到惊讶,我将编辑我的问题。谢谢。
  • Angular 会自动清理内容。来自angular.io/guide/security防止跨站点脚本部分:为了系统地阻止 XSS 错误,Angular默认情况下将所有值视为不受信任。当一个值通过属性、属性、样式、类绑定或插值从模板插入到 DOM 中时,Angular 会清理和转义不受信任的值。

标签: angular typescript sanitize


【解决方案1】:

要将普通 HTML 插入到您的 angular2 应用程序中,您可以使用 [innerHtml] 指令。

<div [innerHtml]="htmlProperty"></div>

这不适用于具有自己的组件和指令的 HTML,至少不是您期望的那样。

但是,如果您确实收到了不安全的 html 警告,您应该在注入之前首先信任 HTML。你必须使用DomSanitizer 来做这样的事情。例如,&lt;h3&gt; 元素被认为是安全的。 &lt;input&gt; 元素不是。

export class AppComponent  {

    private _htmlProperty: string = '<input type="text" name="name">';

    public get htmlProperty() : SafeHtml {
       return this.sr.bypassSecurityTrustHtml(this._htmlProperty);
    }

    constructor(private sr: DomSanitizer){}
}

并让您的模板保持与此相同:

<div [innerHtml]="htmlProperty"></div>

不过有点提醒:

警告:使用不受信任的用户数据调用此方法会使您的应用程序面临 XSS 安全风险!

如果你打算更多地使用这个技术,你可以尝试写一个@Pipe来完成这个任务。

import { Pipe, PipeTransform } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';

@Pipe({
    name: 'trustHtml'
})
export class TrustHtmlPipe implements PipeTransform  {    
   constructor(readonly sr: DomSanitizer){}  

   transform(html: string) : SafeHtml {
      return this.sr.bypassSecurityTrustHtml(html); 
   } 
} 

如果你有这样的管道,你的AppComponent 会变成这个。不要忘记将管道添加到 NgModule 的声明数组中:

@Component({
   selector: 'app',
   template: `<div [innerHtml]="htmlProperty | trustHtml"></div>`
})
export class AppComponent{

    public htmlProperty: string = '<input type="text" name="name">';

} 

或者你也可以写一个@Directive来做同样的事情:

@Directive({
   selector: '[trustHtml]'
})
export class SanitizeHtmlDirective {

    @Input()
    public set trustHtml(trustHtml: string) {
      if (this._trustHtml !== trustHtml) {
        this._trustHtml = trustHtml;
        this.innerHtml = this.sr.bypassSecurityTrustHtml(this.trustHtml);
      }
    }

    @HostBinding('innerHtml')
    innerHtml?: SafeHtml;

    private _trustHtml: string;

    constructor(readonly sr: DomSanitizer){}
}

如果你有这样的指令,你的AppComponent 会变成这个。不要忘记将指令添加到 NgModule 的声明数组中:

@Component({
   selector: 'app',
   template: `<div [trustHtml]="htmlProperty"></div>`
})
export class AppComponent{

    public htmlProperty: string = '<input type="text" name="name">';

} 

【讨论】:

  • 天哪,我试过inner-html。太糟糕了...谢谢!
  • 自.. alpha.51 以来,规格发生了变化,如果我是正确的。 CamelCase 现在无处不在(除了元素标签)。欢迎你:)
  • 我从来没有使用过任何 alpha 版本,马上就进入了 beta,但是,我想我在研究时从一些早期的 alpha 版本中发现了inner-html
  • 请参阅我们需要使用DomSanitizer 的最新文档,如angular.io/docs/ts/latest/api/platform-browser/index/… 所示。已经进行了一些重命名。
  • @JonathanReyes 感谢您的提醒。更新了我的答案
猜你喜欢
  • 1970-01-01
  • 2021-12-25
  • 1970-01-01
  • 1970-01-01
  • 2012-12-22
  • 2014-08-04
  • 2010-12-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多