J'essaie d'obtenir du contenu html tiers (potentiellement dangereux) de ma base de données et de l'insérer dans mon document html.
Comment faire cela en toute sécurité (Protection contre XSS)?
Dans Angular1.x il y avait auparavant $sce
pour assainir l'entrée, comment faire cela dans Angular2? Si je comprends bien, Angular2 le désinfecte automatiquement par défaut, est-ce correct?
Quelque chose comme ça ne fonctionnera pas:
<div class="foo">
{{someBoundValueWithSafeHTML}} // I want HTML from db here
</div>
Pour insérer du code HTML normal dans votre application angular2, vous pouvez utiliser la directive [innerHtml]
.
<div [innerHtml]="htmlProperty"></div>
Cela ne fonctionnera pas avec HTML qui a ses propres composants et directives, du moins pas comme vous vous y attendriez.
Si toutefois vous obtenez un avertissement html dangereux, vous devez d'abord faire confiance à HTML
avant de l'injecter. Vous devez utiliser DomSanitizer
pour une telle chose. Par exemple, un élément <h3>
Est considéré comme sûr. Un élément <input>
Ne l'est pas.
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){}
}
Et que votre modèle reste le même:
<div [innerHtml]="htmlProperty"></div>
Un petit avertissement cependant:
AVERTISSEMENT: appeler cette méthode avec des données utilisateur non fiables expose votre application à des risques de sécurité XSS!
Si vous prévoyez d'utiliser davantage cette technique, vous pouvez essayer d'écrire un @Pipe
pour accomplir cette tâche .
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);
}
}
Si vous avez un tuyau comme celui-ci, votre AppComponent
se changera en ceci. N'oubliez pas d'ajouter le pipe à votre tableau de déclarations de votre NgModule
:
@Component({
selector: 'app',
template: `<div [innerHtml]="htmlProperty | trustHtml"></div>`
})
export class AppComponent{
public htmlProperty: string = '<input type="text" name="name">';
}
Ou vous pouvez écrire un @Directive
pour faire de même:
@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){}
}
Si vous avez une directive comme celle-ci, votre AppComponent
se changera en ceci. N'oubliez pas d'ajouter la directive à votre tableau de déclarations de votre NgModule
:
@Component({
selector: 'app',
template: `<div [trustHtml]="htmlProperty"></div>`
})
export class AppComponent{
public htmlProperty: string = '<input type="text" name="name">';
}