最近在做关于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="Explicitly trusted HTML bypasses ' +
'sanitization."">Hover over this text.</span>');
}]);
</script>
</body>
</html>
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。