ВНИМАНИЕ: очистка URL значения небезопасного стиля

108

Я хочу установить фоновое изображение DIV в шаблоне компонента в моем приложении Angular 2. Однако я продолжаю получать следующее предупреждение в моей консоли, и я не получаю желаемого эффекта ... Я не уверен, блокируется ли динамическое фоновое изображение CSS из-за ограничений безопасности в Angular2 или мой шаблон HTML не работает.

Это предупреждение, которое я вижу на своей консоли (я изменил свой URL-адрес img на /img/path/is/correct.png:

ПРЕДУПРЕЖДЕНИЕ: дезинфицирующий небезопасным значение типа URL (SafeValue должны использовать [свойство] = связывание: /img/path/is/correct.png (см http://g.co/ng/security#xss )) (см Http: // g.co/ng/security#xss ).

Дело в том, что я дезинфицирую то, что вводится в мой шаблон, с помощью DomSanitizationServiceметода Angular2. Вот мой HTML-код в моем шаблоне:

<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>

Вот компонент ...

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;
                }

            }
        }
    }
}

Обратите внимание, когда я просто привязался к шаблону, используя [src] = "image", например:

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

и imageпрошел, используя bypassSecurityTrustUrlвсе, казалось, работает хорошо ... может ли кто-нибудь увидеть, что я делаю не так?

Марк Сэндман
источник
Получили ли вы решение своего вопроса. У меня точно такая же проблема, и я все еще пытаюсь найти решение. Заранее спасибо!
СК.

Ответы:

114

Вы должны обернуть весь urlоператор в bypassSecurityTrustStyle:

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

И имеют

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

В противном случае это не рассматривается как допустимое свойство стиля.

Пол Крюйт
источник
1
PierreDuc, какие мудрые слова можно сказать о том, что фоновое изображение ПРОПУСКАЕТСЯ, как указано выше, но тогда Angular2 молча игнорирует его? Я могу задать новый вопрос, но я думаю, что он вполне уместен для вашего ответа.
Дэвид Пфеффер
@DavidPfeffer Трудно судить, где что-то пойдет не так, не видя кода :) Я использую этот код в последней версии angular2, и он все еще работает ..
Пол Круйт
1
Я понял. Если после обхода дезинфекции значение недействительно, Angular2 игнорирует его.
Дэвид Пфеффер
Вам следует ngStyle, и он будет работать, не вмешиваясь в дезинфекцию.
yglodt
У меня работал в Angular8. Я думаю, что дезинфекция лучше всего ... она существует не зря. @yglodt.
Шон Холлс,
68

Используйте это, чтобы <div [ngStyle]="{'background-image':'url('+imageUrl+')'}"></div>решить проблему для меня.

iRedia Ebikade
источник
Надежно и просто.
Kenmore
Спасибо за добрые слова @Kenmore. Я рад, что смог помочь. Ура.
iRedia Ebikade
@ Sammy-RogersGeek, могу ли я написать такой же код в теге изображения?
Арджун
Ты спас мне день!
VAdaihiep
Красноречиво. Спасибо.
Команда Mindsect
52

Если фоновое изображение с linear-gradient ( *ngFor)

Посмотреть:

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

Класс:

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
Вы спасли мой день
Thamaraiselvam
1
Работает отлично :))
Абхиджит Шривастава
@AbhijitSrivastava Я написал thumbnailMediumIcon = this.sanitizer.bypassSecurityTrustUrl(url ($ {thumbnail}) )и [style.backgroundImage]="thumbnailMediumIcon". Какую версию Angular вы использовали? Я также пробовал фоновое изображение. Это все еще работает? Мне не нравится другой подход?
МТЗ
1
@AbhijitSrivastava Спасибо! Моя ошибка, я передал blob ( thumbnail) вместо URL
МТЗ
1
Не рекомендуется вызывать getBackgroundвнутри представления, потому что Angular должен вызывать bypassSecurityTrustStyleкаждый раз, когда это представление обновляется. Чтобы проверить это, добавьте console.log внутрь, getBackgroundи вы увидите, что эта функция вызывается при каждом щелчке или событии прокрутки пользователя
Марцин
9

Проверьте этот удобный канал для Angular2: Использование:

  1. в SafePipeкоде замените DomSanitizationServiceнаDomSanitizer

  2. предоставьте, SafePipeесли вашNgModule

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

SimoneMSR
источник
8

Судя по документации на https://angular.io/api/platform-browser/DomSanitizer , правильным способом сделать это, по-видимому, является использование sanitize. По крайней мере, в Angular 7 (не знаю, изменилось ли это раньше). Это сработало для меня:

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 + ')');

По поводу SecurityContext см. Https://angular.io/api/core/SecurityContext . В основном это просто перечисление:

enum SecurityContext {
  NONE: 0
  HTML: 1
  STYLE: 2
  SCRIPT: 3
  URL: 4
  RESOURCE_URL: 5
}
Довев Хефец
источник
1
Это самый последний ответ. Его тоже можно сократить:this.sanitizer.bypassSecurityTrustStyle(`url('${this.image} ')`);
Захема
@Zahema Я не считаю, что это эквивалентно предоставленному ответу. bypassSecurityTrustStyleигнорирует безопасность, но sanitize(SecurityContext.STYLE, style)усиливает безопасность. Я бы рекомендовал использовать sanitizeс соответствующими SecurityContext.
Оскар
@Zahema bypassSecurityTrustStyleвозвращает объект, к которому нельзя получить доступ (по крайней мере, я не мог этого сделать) в [ngStyle]. sanitize(SecurityContext.STYLE, style)вместо этого возвращает простую строку.
Александр Финк,
@Oscar Я согласен, но по какой-то причине это не всегда работает должным образом во всех сценариях. bypassSecurityTrustStyleэто в основном грубое принуждение.
Захема
6

У меня возникла та же проблема при добавлении динамического URL-адреса в тег изображения в Angular 7. Я много искал и нашел это решение.

Сначала напишите код ниже в файле компонента.

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

Теперь в теге изображения html вы можете написать вот так.

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

Вы можете писать в соответствии с вашими требованиями вместо item.imageUrl

Получил ссылку с этого сайта. динамические URL-адреса . Надеюсь, это решение вам поможет :)

Арджун
источник
он работает для изображений, но вопрос
касался
3

Существует нерешенная проблема, заключающаяся в том, чтобы распечатать это предупреждение только в том случае, если что-то действительно было продезинфицировано: https://github.com/angular/angular/pull/10272

Я не читал подробно, когда печатается это предупреждение, когда ничего не было продезинфицировано.

Гюнтер Цохбауэр
источник
3
Для тех, кто может сюда прийти: этот вопрос решен. Он выводит предупреждение только в том случае, если он дезинфицировал HTML, а не все время.
flamusdiu
Я хотел знать, это неправильная практика? Следует ли мне попытаться не получать это предупреждение?
Амрит
Вы должны быть очень осторожны, когда применяете это к пользовательскому контенту (например, тексту из поля ввода или пользовательскому контенту, загруженному из базы данных или других источников, которые вы не контролируете. Таким образом вы сообщаете Angular, что небезопасный по своей сути контент должен рассматриваться как Trustworty. Вполне нормально использовать его для статического контента, который вы контролируете, например, констант, переменных среды, передаваемых во время сборки, значений, рассчитываемых только на основе таких безопасных значений.
Гюнтер Цохбауэр
1

Для всех, кто уже делает то, что вам предлагает предупреждение, перед обновлением до Angular 5 мне пришлось сопоставить свои SafeStyleтипы, stringпрежде чем использовать их в шаблонах. После Angular 5 это уже не так. Мне пришлось поменять модели, чтобы image: SafeStyleвместо image: string. Я уже использовал [style.background-image]привязку свойств и обход безопасности по всему URL-адресу.

Надеюсь, это кому-то поможет.

Джейк Смит
источник
0

Поскольку Angular не является специальной библиотекой для очистки, она слишком ревностно относится к подозрительному контенту, чтобы не рисковать. Вы можете делегировать дезинфекцию в специальную библиотеку, например, DOMPurify. Вот библиотека-оболочка, которую я сделал, чтобы легко использовать DOMPurify с Angular.

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

У него есть канал для декларативной дезинфекции HTML:

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

Следует иметь в виду, что DOMPurify отлично подходит для очистки HTML / SVG, но не CSS. Таким образом, вы можете предоставить дезинфицирующее средство CSS Angular для обработки CSS:

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

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

Это внутренний ɵпрефикс hense , но в любом случае команда Angular использует его в своих пакетах именно так.

Waterplea
источник
-1

В моем случае я получил URL-адрес изображения, прежде чем перейти к компоненту отображения, и хочу использовать его в качестве фонового изображения, поэтому, чтобы использовать этот URL-адрес, я должен сообщить Angular, что он безопасен и может быть использован.

В файле .ts

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

В файле .html

<div mat-card-avatar class="nav-header-image" [style.background-image]="userImage"></div>
САНТОШ
источник
Пожалуйста, отредактируйте свой ответ, чтобы объяснить его и отметить, почему это лучший ответ, чем любой из существующих.
Драконьи мысли