AngularJs$sce和$sceDelegate上下文轉義

ys野獸發表於2015-11-27

$sce

$sce 服務是AngularJs提供的一種嚴格上下文轉義服務。

嚴格的上下文轉義服務

嚴格的上下文轉義(SCE)是一種需要在一定的語境中導致AngularJS繫結值被標記為安全使用語境的模式。由使用者通過ng-bind-html繫結任意HTML語句就是這方面的一個例子。我們稱這些上下文轉義為特權或者SCE。

下面程式碼是簡化了的ngBindHtml實現(當然,這不是完整版ngBindHtml原始碼):

  var ngBindHtmlDirective = [`$sce`, function($sce) {
      return function(scope, element, attr) {
        scope.$watch($sce.parseAsHtml(attr.ngBindHtml), function(value) {
          element.html(value || ``);
        });
      };
   }];

支援哪些信任的上下文型別?

$sce.HTML  將HTML程式碼安全的繫結到應用程式中。

$sce.CSS  將CSS樣式程式碼安全的繫結到應用程式中。

$sce.URL  將URL安全的繫結到應用程式中並保證其可用。比如(href,src)

$sce.RESOURCE_URL   將RESOURCE_URL安全的繫結到應用程式中並保證其可用。比如(ng-href,ng-src)

$sce.JS  將JAVASCRIPT程式碼安全的繫結到應用程式中。

如何使$sce服務可用或者不可用?

  angular.module(“myApp”,[]).config([“$sceProvider”,function($sceProvider){
       $sceProvider.enabled(true/false);
  }]);

使用:$sce();

方法

isEnabled();

返回一個boolean,指示是否可啟用SCE。

parseAs(type,expression);

將Angular表示式轉換為一個函式。這類似$parse解析並且當表示式是常量時是相同的。否則,它將呼叫$sce.getTrusted(type,result)將表示式包裝。

type:在SCE的上下文的使用的結果的型別。

expression:被編譯的字串表示式。

trustAs(type,value);

代表$sceDelegate.trustAs。

type:上下文中能安全的被使用的值,如url,resourceUrl,html,js和css。

value:需要被認為是安全或者值的信賴的值。

trustAsHtml(value);

$sceDelegate.trustAs($sce.HTML,value)的快捷方式。

value:被信任的值。

trustAsUrl(value);

$sceDelegate.trustAs($sce.URL,value)的快捷方式。

value:被信任的值。

trustAsResourceUrl(value);

$sceDelegate.trustAs($sce.RESOURCE_URL,value)的快捷方式。

value:被信任的值。

trustAsJs(value);

$sceDelegate.trustAs($sce.JS,value)的快捷方式。

value:被信任的值。

getTrusted(type,maybeTrusted);

代表$sceDelegate.getTrusted。因此,得到了$sce的結果。如果查詢的上下文型別是一個創造型的型別,則呼叫trustAs()並且返回原來提供的值。如果這個條件不滿足,則丟擲一個異常。

getTrustedHtml(value);

$sceDelegate.getTrusted ($sce.HTML,value)的快捷方式。

value:通過$sce.getTrusted執行後的值。

getTrustedCss(value);

$sceDelegate.getTrusted ($sce.CSS,value)的快捷方式。

value:通過$sce.getTrusted執行後的值。

getTrustedUrl(value);

$sceDelegate.getTrusted ($sce.URL,value)的快捷方式。

value:通過$sce.getTrusted執行後的值。

getTrustedResourceUrl(value);

$sceDelegate.getTrusted ($sce.RESOURCE_URL,value)的快捷方式。

value:通過$sce.getTrusted執行後的值。

getTrustedJs(value);

$sceDelegate.getTrusted ($sce.JS,value)的快捷方式。

value:通過$sce.getTrusted執行後的值。

parseAsHtml(expression);

$sce.parseAs ($sce.HTML,value)的快捷方式。

value:被編譯的字串表示式。

parseAsCss(expression);

$sce.parseAs ($sce.CSS,value)的快捷方式。

value:被編譯的字串表示式。

parseAsUrl(expression);

$sce.parseAs ($sce.URL,value)的快捷方式。

value:被編譯的字串表示式。

parseAsResourceUrl(expression);

$sce.parseAs ($sce.RESOURCE_URL,value)的快捷方式。

value:被編譯的字串表示式。

parseAsJs(expression);

$sce.parseAs ($sce.JS,value)的快捷方式。

value:被編譯的字串表示式。

使用方式:

  <div ng-app="Demo" ng-controller="testCtrl as ctrl">
      <textarea ng-model="ctrl.jsContext"></textarea>
      <pre ng-bind="ctrl.jsBody"></pre>
      <button ng-click="ctrl.runJs()">Run</button>
      <div ng-bind-html="ctrl.htmlText" class="myCss"></div>
  </div>
  (function () {
      angular.module(`Demo`, [])
      .controller(`testCtrl`, ["$sce","$scope",testCtrl]);
      function testCtrl($sce,$scope) {
          var vm = this;
          $scope.$watch("ctrl.jsContext",function(n){
             vm.jsBody = n;
          });
          this.runJs = function() {
              eval(vm.jsBody.toString());
          };
          vm.htmlText = "<h2>Hello World</h2>";
          vm.htmlText =$sce.trustAsHtml(this.htmlText);
      }
  }());

放在filter使用:

  <div ng-app="Demo" ng-controller="testCtrl as ctrl">
       <div ng-bind-html="ctrl.htmlText | trust:`html`"></div>
  </div>
  (function () {
      angular.module(`Demo`, [])
      .filter("trust",["$sce",trust])
      .controller(`testCtrl`, testCtrl);
      function trust($sce){
          return function(value,type){
            return $sce.trustAs(type,value); 
          }
      };
      function testCtrl() {
          this.htmlText = "<h2>Hello World</h2>";
      }
  }());

上面是一個將不被Angular認定為信任的HTML程式碼字串通過$sce設定為信任的HTML程式碼並且插入的例子,這裡用了個小技巧,也就沒在controller進行這步操作了,直接放到一個filter服務內,只要在需要的地方過濾下即可,並且可指定型別,這裡寫成統一動態選擇型別了。那麼在啥時候需要用到這兩個服務呢?在當使用ng-bind-html繫結html時報錯:Error: [$sce:unsafe]Attempting to use an unsafe value in a safe context. 的時候使用。

$sceDelegate

$sceDelegate是一個AngularJs為$sce服務提供嚴格的上下文轉義服務的服務。

通常,你會配置或者重寫$sceDelegate去代替$sce服務以定製AngularJs中的嚴格的上下文轉義機制。當$sce提供眾多的快捷方式,你其實只需要重寫三個核心功能(trustAs,getTrusted和valueOf)來替代事件的工作方式,因為$sce代表了$sceDelegate的這些操作。

當你完成了重寫或配置$sceDelegate用來改變$sce的行為時,一般情況下,需要配置$sceDelegateProvider以代替你用於裝載可信任的AngularJs資源(如template)的白名單和黑名單。

使用:$sceDelegate();

方法

trustAs(type,value);

返回一個在angular中作為指定的使用嚴格的上下文轉義服務上下文中的值的物件使用。

type:上下文中能安全的被使用的值,如url,resourceUrl,html,js和css。

value:需要被認為是安全或者值的信賴的值。

valueOf(value);

如果傳遞的引數被上一個$sceDelegate.trustAs呼叫返回,返回已通過$sceDelegate.trustAs的值。否則返回原先的值。

value:上一個$sceDelegate.trustAs呼叫的結果或者其他任何結果。

getTrusted(type,maybeTrusted);

如果查詢的上下文型別是一個創造型的型別,得到$sceDelegate呼叫的結果並返回最初提供的值。如果這個條件不滿意,丟擲一個異常。

type:需要用到的值的型別。

value:上一個$sceDelegate.trustAs呼叫的結果或者其他任何結果。

使用程式碼(配置白名單/黑名單):

  angular.module(`myApp`, []).config([“$ sceDelegateProvider”,function($sceDelegateProvider) {
    $sceDelegateProvider.resourceUrlWhitelist([“whitelist value”]);
    $sceDelegateProvider.resourceUrlBlacklist([“blacklist value”]);
  }]);


相關文章