angular - Angular2'de girdiyi temizle
Veritabanımdan üçüncü taraf (potansiyel olarak güvenli olmayan) HTML içeriğini almaya ve bunu HTML belgeme eklemeye çalışıyorum.
Bunu güvenli bir şekilde nasıl yapabilirim (XSS koruması) ?
Angular1.x'te girdiyi temizlemek için $sce kullanılırdı, Angular2'de bunu nasıl yapabilirim? Anladığım kadarıyla, Angular2 bunu varsayılan olarak otomatik olarak temizliyor, doğru mu?
Böyle bir şey işe yaramayacaktır:
<div class="foo">
{{someBoundValueWithSafeHTML}} // I want HTML from db here
</div>
Cevap #1
Angular2 uygulamanıza normal HTML eklemek için [innerHtml] yönergesini kullanabilirsiniz.
<div [innerHtml]="htmlProperty"></div>
Bu, kendi bileşenleri ve yönergeleri olan HTML ile işe yaramayacak, en azından beklediğiniz şekilde değil.
Ancak, eğer bir güvenli olmayan html uyarısı alırsanız, enjekte etmeden önce HTML'e güvenmelisiniz. Böyle bir şey için DomSanitizer'ı kullanmanız gerekir. Örneğin, bir <h3> elementi güvenli kabul edilir. Bir <input> elementi ise güvenli değildir.
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){}
}
Ve şablonunuz bununla aynı kalsın:
<div [innerHtml]="htmlProperty"></div>
Ama küçük bir uyarı:
UYARI: Bu yöntemi güvenilmeyen kullanıcı verileri ile çağırmak, uygulamanızı XSS güvenlik risklerine maruz bırakır!
Bu tekniği daha fazla kullanmayı planlıyorsanız, bu görevi yerine getirmek için bir @Pipe yazmayı deneyebilirsiniz.
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);
}
}
Eğer böyle bir pipe'ınız varsa, sizin AppComponentiniz buna dönüşecektir. Pipe'ı NgModuleünüzün declarations array'ine eklemeyi unutmayın:
@Component({
selector: 'app',
template: `<div [innerHtml]="htmlProperty | trustHtml"></div>`
})
export class AppComponent{
public htmlProperty: string = '<input type="text" name="name">';
}
Ya da aynı şeyi yapmak için bir @Directive yazabilirsiniz:
@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){}
}
Eğer böyle bir direktifiniz varsa, sizin AppComponent şu şekilde değişecektir. Direktifi NgModule’ünüzün declarations dizisine eklemeyi unutmayın:
@Component({
selector: 'app',
template: `<div [trustHtml]="htmlProperty"></div>`
})
export class AppComponent{
public htmlProperty: string = '<input type="text" name="name">';
}
