OSTRZEŻENIE: odkażanie niebezpiecznego adresu URL wartości stylu


107

Chcę ustawić obraz tła DIV w szablonie komponentów w mojej aplikacji Angular 2. Jednak wciąż otrzymuję następujące ostrzeżenie w mojej konsoli i nie osiągam pożądanego efektu ... Nie jestem pewien, czy dynamiczny obraz tła CSS jest blokowany z powodu ograniczeń bezpieczeństwa w Angular2, czy też mój szablon HTML jest uszkodzony.

To jest ostrzeżenie, które widzę na mojej konsoli (zmieniłem mój adres URL img na /img/path/is/correct.png:

OSTRZEŻENIE: dezynfekcja adresu URL wartości niebezpiecznego stylu (SafeValue musi używać [property] = binding: /img/path/is/correct.png (patrz http://g.co/ng/security#xss )) (patrz http: // g.co/ng/security#xss ).

Chodzi o to, że dezynfekuję to, co jest wstrzykiwane do mojego szablonu za pomocą programu DomSanitizationServicew Angular2. Oto mój kod HTML, który mam w szablonie:

<div>
    <div>
        <div class="header"
             *ngIf="image"
             [style.background-image]="'url(' + image + ')'">
        </div>

        <div class="zone">
            <div>
                <div>
                    <h1 [innerHTML]="header"></h1>
                </div>
                <div class="zone__content">
                    <p
                       *ngFor="let contentSegment of content"
                       [innerHTML]="contentSegment"></p>
                </div>
            </div>
        </div>
    </div>
</div>

Oto element ...

Import {
    DomSanitizationService,
    SafeHtml,
    SafeUrl,
    SafeStyle
} from '@angular/platform-browser';

@Component({
               selector: 'example',
               templateUrl: 'src/content/example.component.html'
           })
export class CardComponent implements OnChanges {

    public header:SafeHtml;
    public content:SafeHtml[];
    public image:SafeStyle;
    public isActive:boolean;
    public isExtended:boolean;

    constructor(private sanitization:DomSanitizationService) {
    }

    ngOnChanges():void {
        map(this.element, this);

        function map(element:Card, instance:CardComponent):void {
            if (element) {
                instance.header = instance.sanitization.bypassSecurityTrustHtml(element.header);

                instance.content = _.map(instance.element.content, (input:string):SafeHtml => {
                    return instance.sanitization.bypassSecurityTrustHtml(input);
                });

                if (element.image) {
                    /* Here is the problem... I have also used bypassSecurityTrustUrl */ 
                    instance.image = instance.sanitization.bypassSecurityTrustStyle(element.image);
                } else {
                    instance.image = null;
                }

            }
        }
    }
}

Zwróć uwagę, że kiedy po prostu związałem się z szablonem za pomocą [src] = "obraz", na przykład:

<div *ngIf="image">
    <img [src]="image">
</div>

i imagezostał zaliczony, gdy bypassSecurityTrustUrlwszystko wydawało się działać dobrze ... czy ktoś może zobaczyć, co robię źle?


Czy otrzymałeś rozwiązanie swojego pytania. Mam dokładnie ten sam problem i wciąż próbuję znaleźć rozwiązanie. Z góry dziękuję!
SK.

Odpowiedzi:


112

Musisz zawrzeć całe urlzestawienie w bypassSecurityTrustStyle:

<div class="header" *ngIf="image" [style.background-image]="image"></div>

I mają

this.image = this.sanitization.bypassSecurityTrustStyle(`url(${element.image})`);

W przeciwnym razie nie jest postrzegana jako prawidłowa właściwość stylu


1
PierreDuc, czy są jakieś mądre słowa, gdy obraz tła jest pomijany jak powyżej, ale wtedy Angular2 po cichu to ignoruje? Mogę zadać nowe pytanie, ale myślę, że jest ono dość związane z Twoją odpowiedzią.
David Pfeffer,

@DavidPfeffer Trudno jest ocenić, gdzie coś pójdzie nie tak, nie widząc żadnego kodu :) Używam tego kodu w najnowszym angular2 i nadal działa ..
Poul Kruijt

1
Rozgryzłem to. Po ominięciu oczyszczania, jeśli wartość jest nieprawidłowa, Angular2 po cichu ją ignoruje.
David Pfeffer,

Powinieneś ngStyle i po prostu zadziała bez bałaganu podczas odkażania.
yglodt

Pracował dla mnie w Angular8. Myślę, że odkażanie jest najlepsze ... nie bez powodu. @yglodt.
Sean Halls

67

Użyj tego, aby <div [ngStyle]="{'background-image':'url('+imageUrl+')'}"></div>rozwiązać problem za mnie.


Bezpieczne i proste.
Kenmore,

Dzięki za miłe słowa @Kenmore. Cieszę się, że mogłem być pomocny. Twoje zdrowie.
iRedia Ebikade,

@ Sammy-RogersGeek Czy mogę napisać ten sam kod w tagu obrazu?
Arjun

Ratujesz mój dzień!
VAdaihiep

Wymowny. Dziękuję Ci.
Mindsect Team

52

Jeśli obraz tła z liniowym gradientem ( *ngFor)

Widok:

<div [style.background-image]="getBackground(trendingEntity.img)" class="trending-content">
</div>

Klasa:

import { DomSanitizer, SafeResourceUrl, SafeUrl } from '@angular/platform-browser';

constructor(private _sanitizer: DomSanitizer) {}

getBackground(image) {
    return this._sanitizer.bypassSecurityTrustStyle(`linear-gradient(rgba(29, 29, 29, 0), rgba(16, 16, 23, 0.5)), url(${image})`);
}

1
uratowałeś mi dzień
Thamaraiselvam

1
Działa idealnie :))
Abhijit Srivastava

@AbhijitSrivastava Napisałem thumbnailMediumIcon = this.sanitizer.bypassSecurityTrustUrl(url ($ {thumbnail}) )i [style.backgroundImage]="thumbnailMediumIcon". Z jakiej wersji Angular korzystałeś? Spróbowałem także obrazu tła. Czy to nadal działa? Nie podoba mi się inne podejście?
MTZ

1
@AbhijitSrivastava Thanks! Mój błąd, podałem blob ( thumbnail) zamiast adresu URL
MTZ

1
Nie zaleca się wywoływania getBackgroundwewnątrz widoku, ponieważ Angular musi wywoływać za bypassSecurityTrustStylekażdym razem, gdy ten widok jest odświeżany. Aby przetestować, dodaj console.log do środka getBackgroundi zobaczysz, że funkcja jest wywoływana przy każdym zdarzeniu kliknięcia lub przewijania użytkownika
Marcin

9

Sprawdź poręczną rurkę dla Angular2: Zastosowanie:

  1. w SafePipekodzie, zastąpić DomSanitizationServicezDomSanitizer

  2. podaj, SafePipejeśli twójNgModule

  3. <div [style.background-image]="'url(' + your_property + ')' | safe: 'style'"></div>


8

Opierając się na dokumentach na https://angular.io/api/platform-browser/DomSanitizer , właściwym sposobem na to wydaje się być użycie sanitize. Przynajmniej w Angular 7 (nie wiem, czy to się zmieniło od wcześniej). To zadziałało dla mnie:

import { Component, OnInit, Input, SecurityContext } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';

constructor(
    private sanitizer: DomSanitizer
) { }

this.sanitizer.sanitize(SecurityContext.STYLE, 'url(' + this.image + ')');

Ponownie SecurityContext, zobacz https://angular.io/api/core/SecurityContext . Zasadniczo to tylko to wyliczenie:

enum SecurityContext {
  NONE: 0
  HTML: 1
  STYLE: 2
  SCRIPT: 3
  URL: 4
  RESOURCE_URL: 5
}

1
To jest najbardziej aktualna odpowiedź. Można to również skrócić:this.sanitizer.bypassSecurityTrustStyle(`url('${this.image} ')`);
Zahema

@Zahema Nie uważam, że jest to odpowiednik udzielonej odpowiedzi. bypassSecurityTrustStyleignoruje bezpieczeństwo, a sanitize(SecurityContext.STYLE, style)wzmacnia bezpieczeństwo. Polecam używanie sanitizez odpowiednim SecurityContext.
Oscar

@Zahema bypassSecurityTrustStylezwraca obiekt, do którego nie można uzyskać dostępu (przynajmniej nie mogłem tego zrobić) w [ngStyle]. sanitize(SecurityContext.STYLE, style)zamiast tego zwraca zwykły ciąg.
Alexander Fink

@Oscar Zgadzam się, ale z jakiegoś powodu nie zawsze działa to zgodnie z oczekiwaniami we wszystkich scenariuszach. bypassSecurityTrustStylejest po prostu brutalnym wymuszaniem tego.
Zahema

6

Ten sam problem napotkałem podczas dodawania dynamicznego adresu URL w tagu obrazu w Angular 7. Dużo szukałem i znalazłem to rozwiązanie.

Najpierw napisz poniższy kod w pliku komponentu.

constructor(private sanitizer: DomSanitizer) {}
public getSantizeUrl(url : string) {
    return this.sanitizer.bypassSecurityTrustUrl(url);
}

Teraz w swoim tagu graficznym HTML możesz pisać w ten sposób.

<img class="image-holder" [src]=getSantizeUrl(item.imageUrl) />

Możesz pisać zgodnie z wymaganiami zamiast item.imageUrl

Mam odniesienie z tej strony. dynamiczne adresy URL . Mam nadzieję, że to rozwiązanie Ci pomoże :)


działa w przypadku obrazów, ale pytanie dotyczyło adresu URL w stylu, używania jako obrazu tła, na co ta odpowiedź nie ma związku
Amirreza

3

Istnieje otwarty problem, aby wydrukować to ostrzeżenie tylko wtedy, gdy rzeczywiście coś zostało odkażone: https://github.com/angular/angular/pull/10272

Nie czytałem szczegółowo, kiedy to ostrzeżenie jest drukowane, gdy nic nie zostało odkażone.


3
Dla tych, którzy mogą tu przyjść: ten problem został rozwiązany. Wyświetla ostrzeżenie tylko wtedy, gdy oczyszcza HTML, a nie cały czas.
flamusdiu

Chciałem wiedzieć, czy robienie tego jest złą praktyką? Czy powinienem spróbować nie otrzymać tego ostrzeżenia?
Amrit

Powinieneś być bardzo ostrożny, kiedy stosujesz to do treści dostarczanych przez użytkownika (takich jak tekst z pola wejściowego lub zawartość użytkownika ładowana z bazy danych lub innych źródeł, nad którymi nie masz kontroli. W ten sposób możesz powiedzieć Angularowi, że z natury niebezpieczne treści powinny być traktowane jako godne zaufania. Jednak używanie go do statycznej zawartości, którą kontrolujesz, jak stałe, zmienne środowiskowe przekazywane podczas budowania, wartości obliczane tylko z takich bezpiecznych wartości, jest całkowicie w porządku.
Günter Zöchbauer,

1

Dla każdego, kto już robi to, co sugeruje ostrzeżenie, przed aktualizacją do Angular 5 musiałem zmapować moje SafeStyletypy stringprzed użyciem ich w szablonach. Po Angular 5 już tak nie jest. Musiałem zmienić moje modele, aby mieć image: SafeStylezamiast image: string. Używałem już [style.background-image]powiązania właściwości i pomijania zabezpieczeń na całym adresie URL.

Mam nadzieję, że to komuś pomoże.


0

Ponieważ Angular nie jest wyspecjalizowaną biblioteką do odkażania, jest nadgorliwym wobec podejrzanych treści, aby nie podejmować żadnego ryzyka. Możesz delegować czyszczenie do dedykowanej biblioteki, na przykład - DOMPurify. Oto biblioteka opakowań, którą stworzyłem, aby łatwo używać DOMPurify z Angular.

https://github.com/TinkoffCreditSystems/ng-dompurify

Ma potok do deklaratywnego oczyszczenia HTML:

<div [innerHtml]="value | dompurify"></div>

Należy pamiętać, że DOMPurify doskonale nadaje się do czyszczenia HTML / SVG, ale nie CSS. Możesz więc udostępnić narzędzie do odkażania CSS Angulara do obsługi CSS:

import {NgModule, ɵ_sanitizeStyle} from '@angular/core';
import {SANITIZE_STYLE} from '@tinkoff/ng-dompurify';

@NgModule({
    // ...
    providers: [
        {
            provide: SANITIZE_STYLE,
            useValue: ɵ_sanitizeStyle,
        },
    ],
    // ...
})
export class AppModule {}

Jest to ɵprefiks wewnętrzny - hense , ale tak i tak zespół Angular używa go również we własnych pakietach.


-1

W moim przypadku otrzymałem adres URL obrazu przed przejściem do komponentu wyświetlania i chcę go użyć jako obrazu tła, więc aby użyć tego adresu URL, muszę powiedzieć Angularowi, że jest bezpieczny i można go użyć.

W pliku .ts

userImage: SafeStyle;
ngOnInit(){
    this.userImage = this.sanitizer.bypassSecurityTrustStyle('url(' + sessionStorage.getItem("IMAGE") + ')');
}

W pliku .html

<div mat-card-avatar class="nav-header-image" [style.background-image]="userImage"></div>

Zmień swoją odpowiedź, aby ją wyjaśnić i zanotuj, dlaczego jest to lepsza odpowiedź niż którakolwiek z istniejących.
Dragonthoughts,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.