一、ng-bing-html指令问题
需求:我需要将一个变量$scope.x = '<a href="http://www.baidu.com/">百度一下</a>'绑定到angular的视图上,希望视图上显示的一个链接.
1.如果,我采用ng-bind="x",或者{{x}},我在视图看到的结果就是上面那个字符串,就说里面的“<”和“>”都被转义了.
2.如果,我在用ng-bind-html,视图上什么都没有,并且会抛出一个错误:"Attempting to use an unsafe value in a safe context."
问题来了,该怎么解决呢?
二、什么是SCE?
SCE,即strict contextual escaping,我的理解是 严格的上下文隔离,即angularjs严格的控制上下文访问。
由于angular默认是开启SCE的,因此也就是说默认会拒绝一些不安全的行为,比如你使用了某个第三方的脚本或者库、加载了一段html等等。
这样做确实是安全了,避免一些跨站XSS,但是有时候我们自己想要加载特定的文件,这时候怎么办呢?
此时可以通过$sce服务把一些地址变成安全的、授权的链接...简单地说,就像告诉门卫,这个陌生人其实是我的好朋友,很值得信赖,不必拦截它!
常用的方法有:
$sce.trustAs(type,name);
$sce.trustAsHtml(value);
$sce.trustAsUrl(value);
$sce.trustAsResourceUrl(value);
$sce.trustAsJs(value);
其中后面的几个都是基于第一个api使用的,比如trsutAsUrl其实调用的是trsutAs($sce.URL,"xxxx");
其中type可选的值为:
$sce.HTML $sce.CSS $sce.URL //a标签中的href , img标签中的src $sce.RESOURCE_URL //ng-include,src或者ngSrc,比如iframe或者Object $sce.JS
三、$sce如何使用
1.将$sce用于指令编写(例1)
在指令值,一般需要操作dom,在添加元素时,如果要将传入的变量直接作为dom元素进行添加,就会可能会带来跨站风险,这时就需要,用$sce.getTrustedXXX从变量中获取受信任的数据。
例1:(这里的myTable指令需要插入html;x.data.Table是一段html的table字符串。)
html
<my-table table="x" ng-bind-html="x.data.Table | trustHtml"></my-table>
js
// 报表指令 app.directive("myTable", function () { return { restrict: 'AECM', template: '<div ng-transclude>{{cont}}</div>', replace: true, transclude: true, scope: { cont: '=table' } }; });
// 添加对html的信任 app.filter('trustHtml', function ($sce) { return function (input) { return $sce.trustAsHtml(input); } });
2.在controller中使用(例2)
例2:
<!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"> <iframe width="100%" height="100%" seamless frameborder="0" ng-src="{{trustSrc}}"></iframe> </div> <script type="text/javascript"> angular.module('mySceApp',[]) .controller('AppController', ['$scope','$sce',function($scope,$sce) { $scope.trustSrc = $sce.trustAs($sce.RESOURCE_URL,"http://map.baidu.com/"); // $scope.trustSrc = $sce.trustAsResourceUrl("http://map.baidu.com/");//等同于这个方法 }]); </script> </body> </html>