【问题标题】:<img>: Unsafe value used in a resource URL context<img>:资源 URL 上下文中使用的不安全值
【发布时间】:2016-10-22 00:17:39
【问题描述】:

自从升级到最新的 Angular 2 候选版本后,我的 img 标签:

<img class='photo-img' [hidden]="!showPhoto1" src='{{theMediaItem.photoURL1}}'>

正在引发浏览器错误:

原始异常:错误:资源 URL 上下文中使用了不安全的值

url的值为:

http://veeu-images.s3.amazonaws.com/media/userphotos/116_1464645173408_cdv_photo_007.jpg

编辑:

我已经尝试过在其他解决方案中提出的建议,该问题应该是重复的,但我得到了同样的错误。

我已将以下代码添加到控制器中:

import {DomSanitizationService} from '@angular/platform-browser';

@Component({
  templateUrl: 'build/pages/veeu/veeu.html'
})
export class VeeUPage {
  static get parameters() {
    return [[NavController], [App], [MenuController], [DomSanitizationService]];
  }

  constructor(nav, app, menu, sanitizer) {

    this.app = app;
    this.nav = nav;
    this.menu = menu;
    this.sanitizer = sanitizer;

    this.theMediaItem.photoURL1 = this.sanitizer.bypassSecurityTrustUrl(this.mediaItems[1].url);
  }

我仍然收到相同的错误消息。

EDIT2:

我也把html改成了:

<img class='photo-img' [hidden]="!showPhoto1" [src]='theMediaItem.photoURL1'>

我仍然收到相同的错误消息

【问题讨论】:

  • 我不清楚我应该改变什么。我是否将 src="{{something.else}}" 更改为 [src]="something.else"?
  • 完全正确:[src]='theMediaItem.photoURL1'
  • 是的,我试过了,我得到了同样的错误信息。
  • 你使用的是哪个 Angular2 版本?
  • 我想我正在使用 2.0.0-beta.15(我正在使用 ionic 并且不完全确定如何检查)抱歉我添加代码的方式我不清楚协议。

标签: angular


【解决方案1】:

管道

    // Angular
    import { Pipe, PipeTransform } from '@angular/core';
    import { DomSanitizer, SafeHtml, SafeStyle, SafeScript, SafeUrl, SafeResourceUrl } from '@angular/platform-browser';
    
    /**
     * Sanitize HTML
     */
    @Pipe({
      name: 'safe'
    })
    export class SafePipe implements PipeTransform {
      /**
       * Pipe Constructor
       *
       * @param _sanitizer: DomSanitezer
       */
      // tslint:disable-next-line
      constructor(protected _sanitizer: DomSanitizer) {
      }
    
      /**
       * Transform
       *
       * @param value: string
       * @param type: string
       */
      transform(value: string, type: string): SafeHtml | SafeStyle | SafeScript | SafeUrl | SafeResourceUrl {
        switch (type) {
          case 'html':
            return this._sanitizer.bypassSecurityTrustHtml(value);
          case 'style':
            return this._sanitizer.bypassSecurityTrustStyle(value);
          case 'script':
            return this._sanitizer.bypassSecurityTrustScript(value);
          case 'url':
            return this._sanitizer.bypassSecurityTrustUrl(value);
          case 'resourceUrl':
            return this._sanitizer.bypassSecurityTrustResourceUrl(value);
          default:
            return this._sanitizer.bypassSecurityTrustHtml(value);
        }
      }
    }

模板

{{ data.url | safe:'url' }}

就是这样!

注意:你不应该需要它,但这里是管道的组件使用

      // Public properties
      itsSafe: SafeHtml;

      // Private properties
      private safePipe: SafePipe = new SafePipe(this.domSanitizer);
    
      /**
       * Component constructor
       *
       * @param safePipe: SafeHtml
       * @param domSanitizer: DomSanitizer
       */
      constructor(private safePipe: SafePipe, private domSanitizer: DomSanitizer) {
      }
    
      /**
       * On init
       */
      ngOnInit(): void {
        this.itsSafe = this.safePipe.transform('<h1>Hi</h1>', 'html');
      }

【讨论】:

    【解决方案2】:

    使用安全管道修复它。

    • 如果您没有,请创建一个安全管道。

      ng g pipe safe

    • 在 app.module.ts 中添加安全管道

      declarations: [SafePipe]

    • 在你的 ts 中声明安全管道

    导入 Dom Sanitizer 和 Safe Pipe 以安全访问 url

    import { Pipe, PipeTransform} from '@angular/core';
    import { DomSanitizer } from "@angular/platform-browser";
    
    @Pipe({ name: 'safe' })
    
    export class SafePipe implements PipeTransform {
    
    constructor(private sanitizer: DomSanitizer) { }
    transform(url) {
     return this.sanitizer.bypassSecurityTrustResourceUrl(url);
      }
    }
    
    • 使用 src url 添加安全

    【讨论】:

    • 太棒了!有一件事,不应该是“ng g pipe safe”而不是“ng g c pipe safe”,什么显然行不通?
    【解决方案3】:

    可以将图片设置为背景图片以避免unsafe url错误:

    <div [style.backgroundImage]="'url(' + imageUrl + ')'" class="show-image"></div>
    

    CSS:

    .show-image {
        width: 100px;
        height: 100px;
        border-radius: 50%;
        background-size: cover;        
    }
    

    【讨论】:

      【解决方案4】:

      默认情况下,Angular 将所有值都视为不受信任。当一个值通过属性、属性、样式、类绑定或插值从模板插入到 DOM 中时,Angular 会清理和转义不受信任的值。

      因此,如果您直接操作 DOM 并插入内容,则需要对其进行清理,否则 Angular 会出错。

      我为此创建了管道 SanitizeUrlPipe

      import { PipeTransform, Pipe } from "@angular/core";
      import { DomSanitizer, SafeHtml } from "@angular/platform-browser";
      
      @Pipe({
          name: "sanitizeUrl"
      })
      export class SanitizeUrlPipe implements PipeTransform {
      
          constructor(private _sanitizer: DomSanitizer) { }
      
          transform(v: string): SafeHtml {
              return this._sanitizer.bypassSecurityTrustResourceUrl(v);
          }
      }
      

      这就是你可以使用的方式

      <iframe [src]="url | sanitizeUrl" width="100%" height="500px"></iframe>
      

      如果您想添加 HTML,那么 SanitizeHtmlPipe 可以提供帮助

      import { PipeTransform, Pipe } from "@angular/core";
      import { DomSanitizer, SafeHtml } from "@angular/platform-browser";
      
      @Pipe({
          name: "sanitizeHtml"
      })
      export class SanitizeHtmlPipe implements PipeTransform {
      
          constructor(private _sanitizer: DomSanitizer) { }
      
          transform(v: string): SafeHtml {
              return this._sanitizer.bypassSecurityTrustHtml(v);
          }
      }
      

      阅读更多关于角度安全的信息here

      【讨论】:

        【解决方案5】:

        最优雅的解决方法:使用管道。 Here is example (my blog). 所以你可以简单地使用url | safe 管道绕过安全性。

        <iframe [src]="url | safe"></iframe>
        

        详情请参阅 npm 上的文档:https://www.npmjs.com/package/safe-pipe

        【讨论】:

        • 这是一个简单的解决方案。谢谢。
        • 它有一些新的使用语法。它在它的 npmjs url 上可用。
        【解决方案6】:

        我通常添加单独的safe pipe 可重用组件如下

        # Add Safe Pipe
        
        import { Pipe, PipeTransform } from '@angular/core';
        import { DomSanitizer } from '@angular/platform-browser';
        
        @Pipe({name: 'mySafe'})
        export class SafePipe implements PipeTransform {
            constructor(private sanitizer: DomSanitizer) {
            }
        
            public transform(url) {
                return this.sanitizer.bypassSecurityTrustResourceUrl(url);
            }
        }
        
        # then create shared pipe module as following 
        
        import { NgModule } from '@angular/core'; 
        import { SafePipe } from './safe.pipe';
        @NgModule({
            declarations: [
                SafePipe
            ],
            exports: [
                SafePipe
            ]
        })
        export class SharedPipesModule {
        }
        
        # import shared pipe module in your native module
        
        @NgModule({
            declarations: [],
            imports: [
                SharedPipesModule,
            ],
        })
        export class SupportModule {
        }
        
        <!-------------------
        call your url (`trustedUrl` for me) and add `mySafe` as defined in Safe Pipe
        ---------------->
        <div class="container-fluid" *ngIf="trustedUrl">
            <iframe [src]="trustedUrl | mySafe" align="middle" width="100%" height="800" frameborder="0"></iframe>
        </div>
        

        【讨论】:

          【解决方案7】:
          import {DomSanitizationService} from '@angular/platform-browser';
          @Component({
           templateUrl: 'build/pages/veeu/veeu.html'
           })
            export class VeeUPage {
               trustedURL:any;
                static get parameters() {
                         return [NavController, App, MenuController, 
                        DomSanitizationService];
                  }
                constructor(nav, app, menu, sanitizer) {
                  this.app = app;
                  this.nav = nav;
                  this.menu = menu;
                  this.sanitizer = sanitizer;  
                  this.trustedURL  = sanitizer.bypassSecurityTrustUrl(this.mediaItems[1].url);
                  } 
           }
          
          
          
           <iframe [src]='trustedURL' width="640" height="360" frameborder="0"
             webkitallowfullscreen mozallowfullscreen allowfullscreen>
          </iframe>
          
          
          User property binding instead of function.
          

          【讨论】:

            【解决方案8】:

            我正在使用 rc.4,此方法适用于 ES2015(ES6):

            import {DomSanitizationService} from '@angular/platform-browser';
            
            @Component({
              templateUrl: 'build/pages/veeu/veeu.html'
            })
            export class VeeUPage {
              static get parameters() {
                return [NavController, App, MenuController, DomSanitizationService];
              }
            
              constructor(nav, app, menu, sanitizer) {
            
                this.app = app;
                this.nav = nav;
                this.menu = menu;
                this.sanitizer = sanitizer;    
              }
            
              photoURL() {
                return this.sanitizer.bypassSecurityTrustUrl(this.mediaItems[1].url);
              }
            }
            

            在 HTML 中:

            <iframe [src]='photoURL()' width="640" height="360" frameborder="0"
                webkitallowfullscreen mozallowfullscreen allowfullscreen>
            </iframe>
            

            使用函数将确保值在清理后不会改变。另请注意,您使用的清理功能取决于上下文。

            对于图像,bypassSecurityTrustUrl 可以使用,但对于其他用途,您需要参考文档

            https://angular.io/docs/ts/latest/api/platform-browser/index/DomSanitizer-class.html

            【讨论】:

            • 什么是“rc4”(以及后来的Helzgate refers to RC3)?我的意思是,我如何将其映射到 github 版本?在 github 和 npm 中,我只看到 2.4.4 或 2.4.5 之类的版本。我目前在 2.4.4 上,似乎 DomSanitizer 发生了变化;所以这是您需要的导入:import {DomSanitizer} from '@angular/platform-browser';
            • 哦,我认为 angular's github branches 将引用 2.4.x,但 github tags 将引用候选版本,例如 @ 987654330@。我可以看到in rc3,例如这个类仍然被命名为DomSanitizationService
            • this.sanitizer.bypassSecurityTrustResourceUrl(url) 用于视频
            • 在使用之前请仔细阅读文档:bypassSecurityTrustUrl() 警告: 使用不受信任的用户数据调用此方法会将您的应用程序暴露给 XSS安全风险! 在我看来,这样做是不安全的,除非您真的确定图像源是受信任的。即使它来自服务器,如果它是由用户上传的,也有可能利用这样的解决方案。
            • 不要使用 src="{{photoUrl()}}" 因为这仍然会引发异常? 所以 [src]="photoUrl()" 可以解决问题。
            【解决方案9】:

            您可以向视图公开 sanitizer,或者公开将调用转发到 bypassSecurityTrustUrl 的方法

            <img class='photo-img' [hidden]="!showPhoto1" 
                [src]='sanitizer.bypassSecurityTrustUrl(theMediaItem.photoURL1)'>
            

            【讨论】:

            • 感谢您提醒我,我们可以在构造函数中公开方法并在模板中使用它们。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-10-30
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多