最近在做关于angularjs的项目,后续可能会分享一些关于angularjs的一些小知识或者常见问题!

今天分享的是关于angularjs如何使用$sce控制代码安全。

问题场景:
需求要求,点击按钮,要通过一个http网址打开页面,但是这个页面要使用弹框而不能新开一个窗口,这时候我就想到了iframe,大致代码如下:

在controller里面写到:

var url = 'http://www.baidu.com';
$scope.myUrl = url;

html如下:

<iframe ng-src="{{myUrl}}" height="500" width="800" scrolling="yes"></iframe>

这时候问题来了,打开页面是空白的,然后控制台打印了“Error:[$interpolate:interr]”的类型错误:

图片描述
获取页面元素也发现iframe里面的src值没有获取到:
图片描述

在js里面打印url是有值的,在html里面用其他标签获取url也是有值的,所以最后把问题定位在了iframe上面,最后发现,angularjs是没办法直接传url给iframe的src里面的,需要经过一定的安全过滤。

有两种办法可以解决:
1、最直接最简单的方法,就是直接在url值外层套一个$sce.trustAsResourceUrl(),在controller里面的js改写为:

var url = 'http://www.baidu.com';
$scope.myUrl = $sce.trustAsResourceUrl(url);

2、使用过滤器:新增过滤器

angular.module('app', []).filter('iframeSrc', ['$sce', function($sce) {
    return function(val) {
        return $sce.trustAsResourceUrl(val);
    };
}])

在html里面使用过滤器:

<iframe ng-src="{{myUrl | iframeSrc}}" height="500" width="800" scrolling="yes"></iframe>

以上两种方法都可以解决src的取值问题,关键点就在于$sce.trustAsResourceUrl()上面。

$sce.trustAsResourceUrl()是angularjs中防止用户注入url的一个安全检查方法。

································································································································

由此就引申出关于$sce的一些知识:

(1)在angularJs中为了避免安全漏洞,一些ng-src或者ng-include都会进行安全校验,因此常常会遇到一个iframe中的ng-src无法使用的问题

(2)什么是SCE?SCE,即strict contextual escaping,字面上我理解为严格的上下文访问之类的意思,不知道是否正确,但是从SCE的工作机制上看,他做的就是一种安全检查,将相关语境中存在的注入或者跨站攻击等风险干掉,从而将一些特定的内容(包括html,url,css,js,resourceUrl)标记过信任内容再提供给页面使用。这些默认都是不被angularjs信任的,若是使用过程中有像我这样的需求的话,就可以使用$sce来进行授权信任。

(3)常用的$sce方法和使用场景:

$sce.trustAs(type,name);           //type包括:$sce.HTML,$sce.CSS,$sce.URL,$sce.RESOURCE_URL,$sce.JS,比如trsutAsUrl其实调用的是trsutAs($sce.URL,"xxxx");
$sce.trustAsHtml(value);
$sce.trustAsUrl(value);            //a标签中的href , img标签中的src
$sce.trustAsResourceUrl(value);    //ng-include,src或者ngSrc,比如iframe或者Object
$sce.trustAsJs(value);

后面奉上官网的例子ng-bind-html:

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <script src="http://apps.bdimg.com/libs/angular.js/1.2.16/angular.min.js"></script>
</head>
<body ng-app="mySceApp">
    <div ng-controller="AppController">
      <i ng-bind-html="explicitlyTrustedHtml" id="explicitlyTrustedHtml"></i>
    </div>
    <script type="text/javascript">
        angular.module('mySceApp',[])
        .controller('AppController', ['$scope', '$sce',
          function($scope, $sce) {
            $scope.explicitlyTrustedHtml = $sce.trustAsHtml(
                '<span onmouseover="this.textContent=&quot;Explicitly trusted HTML bypasses ' +
                'sanitization.&quot;">Hover over this text.</span>');
          }]);
    </script>
</body>
</html>

我是帅帅的玉米
632 声望58 粉丝

没有远大理想,只想好好工作、多多赚钱的一只单身狗


引用和评论

0 条评论