警告:清理不安全的样式值网址


107

我想在Angular 2应用程序的组件模板中设置DIV的背景图像。但是,我在控制台中始终收到以下警告,但没有得到预期的效果...我不确定动态CSS背景图像是否由于Angular2中的安全限制而被阻止,或者我的HTML模板是否损坏。

这是我在控制台中看到的警告(我将img网址更改为/img/path/is/correct.png

警告:清理不安全的样式值url(SafeValue必须使用[property] = binding:/img/path/is/correct.png(请参阅http://g.co/ng/security#xss))(请参阅http:// g.co/ng/security#xss)。

问题是我确实使用DomSanitizationServiceAngular2 清理了注入模板的内容。这是模板中的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一切似乎都工作正常的结果……任何人都可以看到我在做什么错吗?


您是否已解决问题。我有完全相同的问题,仍在寻找解决方案。提前致谢!
SK。

Answers:


112

您必须将整个url语句包装在中bypassSecurityTrustStyle

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

并有

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

否则,它不会被视为有效的样式属性


1
PierreDuc,关于绕过背景图像的任何智慧之言,但是Angular2却无声地忽略了它?我可以发布一个新问题,但我认为它与您的答案有密切关系。
David Pfeffer

@DavidPfeffer这是很难判断哪里出了问题,没有看到任何代码:)我在使用了最新angular2此代码,它仍然工作..
波尔Kruijt

1
我想到了。绕过清理之后,如果该值无效,则Angular2会静默忽略它。
David Pfeffer

您应该使用ngStyle,它将在不打扫卫生的情况下正常工作。
yglodt

在Angular8中为我工作。我认为消毒是最好的……它的存在是有原因的。@yglodt。
肖恩·霍尔


52

如果背景图片具有线性渐变(*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
完美的工作:))
Abhijit Srivastava

@AbhijitSrivastava我写了thumbnailMediumIcon = this.sanitizer.bypassSecurityTrustUrl(url($ {thumbnail}))[style.backgroundImage]="thumbnailMediumIcon"。您使用了哪个Angular版本?我也尝试过背景图片。这仍然有效吗?我不喜欢其他方法吗?
MTZ

1
@AbhijitSrivastava谢谢!我的错误是,我通过Blob(thumbnail)而不是URL 传递
MTZ

1
不建议getBackground在视图内部调用,因为Angular必须在bypassSecurityTrustStyle每次刷新视图时调用。要测试内部getBackground是否添加了console.log ,您将看到在每次单击或用户滚动事件时调用该函数
Marcin

9

检查便捷管道中的Angular2:用法:

  1. SafePipe代码中,DomSanitizationServiceDomSanitizer

  2. 提供SafePipe如果NgModule

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


8

根据https://angular.io/api/platform-b​​rowser/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

@Zahema我不认为这等同于提供的答案。bypassSecurityTrustStyle忽略安全性,同时sanitize(SecurityContext.STYLE, style)增强安全性。我建议sanitize与配合使用SecurityContext
奥斯卡

@Zahema bypassSecurityTrustStyle返回在中无法访问(至少我做不到)的对象[ngStyle]sanitize(SecurityContext.STYLE, style)而是返回一个纯字符串。
亚历山大·芬克

@Oscar我同意,但是由于某些原因,它并非总是在所有情况下都能正常工作。bypassSecurityTrustStyle基本上是强行强迫它。
Zahema

6

在Angular 7的Image标签中添加动态url时遇到了相同的问题。我进行了很多搜索并找到了此解决方案。

首先,在组件文件中编写以下代码。

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(用作背景图像),这个答案无关紧要
Amirreza

3

有一个开放的问题,只有在确实进行了某些消毒后才打印此警告:https : //github.com/angular/angular/pull/10272

在未清除任何内容的情况下打印此警告时,我没有详细阅读。


3
对于那些可能会出现的问题:该问题已解决。仅当清除HTML时才打印警告,而不是一直打印。
flamusdiu

我想知道这样做是错误的做法吗?我应该尽量避免收到此警告吗?
阿姆利特

将其应用于用户提供的内容时(例如来自输入字段的文本或从数据库或其他不受您控制的来源加载的用户内容),应格外谨慎。这样,您便会告诉Angular固有的不安全内容应被视为。trustworty这是完全正常,虽然使用它的静态内容,你控制,如常量,环境变量在编译的时候过去了,只值从这样的安全值进行计算。
君特Zöchbauer

1

对于已经做了警告提示的人,在升级到Angular 5之前,我必须先将我的SafeStyle类型映射到string模板中,然后再使用它们。在Angular 5之后,情况不再如此。我必须将模型更改为image: SafeStyle而不是image: string。我已经在使用[style.background-image]属性绑定并绕过整个URL的安全性。

希望这对某人有帮助。


0

由于Angular不是专用的消毒库,因此对可疑内容过分热衷以不承担任何风险。您可以将清理委托给一个专用的库,例如DOMPurify。这是我制作的包装器库,可以轻松地将Angular与DOMPurify结合使用。

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

它具有以声明方式清除HTML的管道:

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

要记住的一件事是DOMPurify非常适合清理HTML / SVG,而不是CSS。因此,您可以提供Angular的CSS清理程序来处理CSS:

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

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

是内部的-香 ɵ前缀,但是,这也是Angular团队在其自己的程序包中使用它的方式。


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

请编辑您的答案以解释它,并注意为什么它比现有答案更好。
Dragonthoughts
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.