AngularJS 使用$sce控制代码安全检查
由于浏览器都有同源加载策略,不能加载不同域下的文件、也不能使用不合要求的协议比如file进行访问。
在angularjs中为了避免安全漏洞,一些ng-src或者ng-include都会进行安全校验,因此常常会遇到 一个iframe中的ng-src无法使用。
什么是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
来自官网的例子: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="explicitly trusted html bypasses ' + 'sanitization."">hover over this text.</span>'); }]); </script> </body> </html>
实际工作中的例子:ng-src链接
<!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://fanyi.youdao.com/"); // $scope.trustsrc = $sce.trustasresourceurl("http://fanyi.youdao.com/");//等同于这个方法 }]); </script> </body> </html>
还有点时间,接着给大家介绍angular中的ng-bind-html指令和$sce服务
angular js的强大之处之一就是他的数据双向绑定这一牛b功能,我们会常常用到的两个东西就是ng-bind和针对form的ng-model。但在我们的项目当中会遇到这样的情况,后台返回的数据中带有各种各样的html标签。如:
$scope.currentwork.description = “hello,<br><b>今天我们去哪里?</b>”
我们用ng-bind-html这样的指令来绑定,结果却不是我们想要的。是这样的
hello,
今天我们去哪里?
怎么办呢?
对于angular 1.2一下的版本我们必须要使用$sce这个服务来解决我们的问题。所谓sce即“strict contextual escaping”的缩写。翻译成中文就是“严格的上下文模式”也可以理解为安全绑定吧。来看看怎么用吧。
controller code:
$http.get('/api/work/get?workid=' + $routeparams.workid).success(function (work) {$scope.currentwork = work;});
html code:
<p> {{currentwork.description}}</p>
我们返回的内容中包含一系列的html标记。表现出来的结果就如我们文章开头所说的那样。这时候我们必须告诉它安全绑定。它可以通过使用$ sce.trustashtml()。该方法将值转换为特权所接受并能安全地使用“ng-bind-html”。所以,我们必须在我们的控制器中引入$sce服务
controller('transferworkstep2', ['$scope','$http','$routeparams','$sce', function ($scope,$http, $routeparams, $sce) { $http.get('/api/work/get?workid=' + $routeparams.workid) .success(function (work) { $scope.currentwork = work; $scope.currentwork.description = $sce.trustashtml($rootscope.currentwork.description); });
html code:
<p ng-bind-html="currentwork.description"></p>
这样结果就完美的呈现在页面上了:
hello
今天我们去哪里?
咱们还可以这样用,把它封装成一个过滤器就可以在模板上随时调用了
app.filter('to_trusted', ['$sce', function ($sce) { return function (text) { return $sce.trustashtml(text); }; }]);
html code:
全选复制放进笔记
<p ng-bind-html="currentwork.description | to_trusted"></p>