データベースからサードパーティの(潜在的に安全でない)htmlコンテンツを取得し、それをhtmlドキュメントに挿入しようとしています。
それを安全に行うにはどうすればよいですか(XSSに対する保護)?
Angular1.xでは、以前は$sce
入力をサニタイズするには、Angular2でどのようにすればよいですか?私が理解する限り、Angular2はデフォルトで自動的にサニタイズしますが、それは正しいですか?
このようなものは機能しません:
<div class="foo">
{{someBoundValueWithSafeHTML}} // I want HTML from db here
</div>
Angular2アプリに通常のHTMLを挿入するには、[innerHtml]
ディレクティブ。
<div [innerHtml]="htmlProperty"></div>
これは、独自のコンポーネントとディレクティブを備えたHTMLでは機能しませんが、少なくとも期待どおりには機能しません。
ただし、安全でないhtml警告が表示される場合は、挿入する前に最初にHTML
を信頼する必要があります。このようなことには DomSanitizer
を使用する必要があります。たとえば、<h3>
要素は安全と見なされます。 <input>
要素はそうではありません。
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(readonlysr: DomSanitizer){}
}
このようなディレクティブがある場合、AppComponent
はこれに変更されます。 NgModule
の宣言配列にディレクティブを追加することを忘れないでください:
@Component({
selector: 'app',
template: `<div [trustHtml]="htmlProperty"></div>`
})
export class AppComponent{
public htmlProperty: string = '<input type="text" name="name">';
}