คำเตือน: การล้าง URL ค่ารูปแบบที่ไม่ปลอดภัย


109

ฉันต้องการตั้งค่าภาพพื้นหลังของ DIV ในเทมเพลตคอมโพเนนต์ในแอพ Angular 2 ของฉัน อย่างไรก็ตามฉันได้รับคำเตือนต่อไปนี้ในคอนโซลของฉันและฉันไม่ได้รับเอฟเฟกต์ที่ต้องการ ... ฉันไม่แน่ใจว่ารูปภาพพื้นหลัง CSS แบบไดนามิกถูกบล็อกเนื่องจากข้อ จำกัด ด้านความปลอดภัยใน Angular2 หรือหากเทมเพลต HTML ของฉันเสีย

นี่คือคำเตือนที่ฉันเห็นในคอนโซลของฉัน (ฉันเปลี่ยน img url เป็น/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ทุกอย่างดูเหมือนจะทำงานได้ดี ... มีใครเห็นไหมว่าฉันทำอะไรผิด?


คุณได้รับคำตอบสำหรับคำถามของคุณหรือไม่ ฉันมีปัญหาเดียวกันทุกประการและยังคงพยายามหาวิธีแก้ไข ขอบคุณล่วงหน้า!
สก.

คำตอบ:


116

คุณต้องสรุป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 ล่าสุดและมันยังใช้งานได้ ..
Poul Kruijt

1
ฉันคิดออกแล้ว หลังจากที่คุณข้ามการฆ่าเชื้อแล้วหากค่าไม่ถูกต้อง Angular2 จะละเว้นค่านี้โดยไม่โต้ตอบ
David Pfeffer

คุณควร ngStyle และมันจะทำงานได้โดยไม่ต้องยุ่งกับการฆ่าเชื้อ
yglodt

ทำงานให้ฉันใน Angular8 ฉันคิดว่าการฆ่าเชื้อเป็นสิ่งที่ดีที่สุด ... มันมีอยู่ด้วยเหตุผล @yglodt.
Sean Halls

70

ใช้สิ่ง<div [ngStyle]="{'background-image':'url('+imageUrl+')'}"></div>นี้เพื่อแก้ปัญหาให้ฉัน


ปลอดภัยและเรียบง่าย
Kenmore

ขอบคุณสำหรับคำพูดของคุณ @Kenmore ฉันดีใจที่ได้รับความช่วยเหลือ ไชโย
iRedia Ebikade

@ Sammy-RogersGeek ฉันสามารถเขียนโค้ดเดียวกันในแท็กรูปภาพได้หรือไม่
Arjun

คุณช่วยวันของฉัน!
VAdaihiep

คมคาย. ขอบคุณ.
Mindsect Team

53

หากภาพพื้นหลังที่มีการไล่ระดับสีเชิงเส้น ( *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 ($ {ภาพขนาดย่อ}) )และ[style.backgroundImage]="thumbnailMediumIcon". คุณใช้ Angular รุ่นอะไร ฉันลองใช้ภาพพื้นหลังด้วย ตอนนี้ยังใช้งานได้ไหม ฉันไม่ชอบวิธีอื่น?
MTZ

1
@AbhijitSrivastava ขอบคุณ! ความผิดพลาดของฉันฉันส่ง blob ( thumbnail) แทน URL
MTZ

1
ไม่แนะนำให้เรียกgetBackgroundภายในมุมมองเนื่องจาก Angular ต้องเรียกbypassSecurityTrustStyleทุกครั้งที่รีเฟรชมุมมอง เพื่อทดสอบว่าเพิ่ม console.log เข้าไปข้างในgetBackgroundและคุณจะเห็นว่าฟังก์ชันนั้นถูกเรียกใช้ในแต่ละคลิกหรือเหตุการณ์การเลื่อนของผู้ใช้
Marcin

9

ตรวจสอบนี้ท่อที่มีประโยชน์สำหรับ Angular2: การใช้งาน:

  1. ในSafePipeรหัสแทนที่DomSanitizationServiceด้วยDomSanitizer

  2. ให้SafePipeถ้าคุณNgModule

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


8

จากเอกสารในhttps://angular.io/api/platform-browser/DomSanitizerดูเหมือนว่าวิธีที่ถูกต้องคือการใช้น้ำยาฆ่าเชื้อ อย่างน้อยใน 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 + ')');

Re 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)ส่งคืนสตริงธรรมดาแทน
Alexander Fink

@Oscar ฉันเห็นด้วย แต่ด้วยเหตุผลบางอย่างมันไม่ได้ผลเสมอไปตามที่คาดไว้ในทุกสถานการณ์ bypassSecurityTrustStyleเป็นเดรัจฉานโดยพื้นฐานบังคับมัน
Zahema

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 แบบไดนามิก หวังว่าโซลูชันนี้จะช่วยคุณได้ :)


ใช้ได้กับรูปภาพ แต่คำถามเกี่ยวกับ URL ในรูปแบบโดยใช้เป็นภาพพื้นหลังซึ่งคำตอบนี้ไม่เกี่ยวข้อง
Amirreza

3

มีการเปิดปัญหาให้พิมพ์คำเตือนนี้หากมีสิ่งที่ถูกสุขอนามัยจริงๆ: https://github.com/angular/angular/pull/10272

ฉันไม่ได้อ่านรายละเอียดเมื่อมีการพิมพ์คำเตือนนี้เมื่อไม่มีการฆ่าเชื้อ


3
สำหรับผู้ที่อาจมาที่นี่: ปัญหานั้นได้รับการแก้ไขแล้ว มันจะพิมพ์คำเตือนเท่านั้นถ้ามันทำความสะอาด HTML ไม่ใช่ตลอดเวลา
flamusdiu

ฉันอยากรู้ว่าการทำเช่นนั้นผิดหรือไม่? ฉันควรพยายามไม่รับคำเตือนนี้หรือไม่?
Amrit

คุณควรใช้ความระมัดระวังเป็นอย่างยิ่งเมื่อคุณใช้สิ่งนี้กับเนื้อหาที่ผู้ใช้ให้มา (เช่นข้อความจากช่องป้อนข้อมูลหรือเนื้อหาของผู้ใช้ที่โหลดจากฐานข้อมูลหรือแหล่งที่มาอื่น ๆ ที่คุณไม่ได้ควบคุมด้วยวิธีนี้คุณจะบอก Angular ว่าเนื้อหาที่ไม่ปลอดภัยโดยเนื้อแท้ควรได้รับการปฏิบัติเป็น trustworty เป็นเรื่องปกติดีแม้ว่าจะใช้กับเนื้อหาคงที่ที่คุณควบคุมเช่นค่าคงที่ตัวแปรสภาพแวดล้อมที่ส่งผ่านในเวลาสร้างค่าที่คำนวณจากค่าที่ปลอดภัยดังกล่าวเท่านั้น
GünterZöchbauer

1

สำหรับใครก็ตามที่กำลังทำตามที่คำเตือนแนะนำให้คุณทำก่อนอัปเกรดเป็น Angular 5 ฉันต้องแมปSafeStyleประเภทของฉันstringก่อนที่จะใช้ในเทมเพลต หลังจาก Angular 5 ก็ไม่เป็นเช่นนั้นอีกต่อไป ฉันมีการเปลี่ยนแปลงรูปแบบของฉันที่จะมีการแทนimage: SafeStyle image: stringฉันใช้การ[style.background-image]ผูกพร็อพเพอร์ตี้และข้ามการรักษาความปลอดภัยของ URL ทั้งหมดแล้ว

หวังว่านี่จะช่วยใครบางคนได้


0

เนื่องจาก Angular ไม่ใช่ไลบรารีสำหรับการฆ่าเชื้อโดยเฉพาะจึงมีความกระตือรือร้นต่อเนื้อหาที่น่าสงสัยเพื่อไม่ให้เกิดความเสี่ยงใด ๆ คุณสามารถมอบหมายการฆ่าเชื้อให้กับไลบรารีเฉพาะตัวอย่างเช่น - DOMPurify นี่คือไลบรารี Wrapper ที่ฉันสร้างขึ้นเพื่อใช้ 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 ใช้ในแพ็คเกจของตัวเองเช่นกัน


-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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.