在我们的 Angular 应用程序中,我们有一个链接,其中包含服务器端的用户内容。所以我们需要告诉 Angular 不要解释该链接内容。否则,如果用户或攻击者将 Angular 绑定表达式放入其中(例如 {{User.Password}}(,那么 Angular 将对其进行评估,从而打开一个安全漏洞 - 一种 XSS 攻击。
ng-non-bindable 大多是这样做的。但是,我们也希望链接本身由 Angular 操纵。
<a href="" class="side-bar-element" ng-class="{ 'side-bar-element-selected': isSiteSelected(@site.value.ID) }">@site.value.Name</a>
@site.value.Name 是用于插入内容的服务器端代码。
如果我们把ng-non-bindable放在a元素上,那么ng类将不起作用。我能看到的唯一解决方案是在其中插入另一个 span/div 并应用ng-non-bindable:
<a href="" class="side-bar-element" ng-class="{ 'side-bar-element-selected': isSiteSelected(@site.value.ID) }"><span ng-non-bindable>@site.value.Name</span></a>
这看起来很笨拙,不得不修改HTML结构才能阻止Angular干扰服务器端数据。
有没有更清洁的解决方案?
理想情况下,我希望ng-non-bindable(或变体(表示"不要绑定内容,否则将此元素视为正常元素"。
如果用户或攻击者将 Angular 绑定表达式放入用户内容(例如 {{User.Password}}(,那么 Angular 将对其进行评估,从而打开一个安全漏洞 - 一种 XSS 攻击。
使用 $delegate
服务降低ng-non-bindable
指令优先级:
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="nonBindableExample">
<script>
function delegator($delegate)
{
/* Override the directive definition object (DDO) */
$delegate[0].priority = 0;
return $delegate;
}
function provider($provide)
{
/* Decorate ng-non-bindable with a proxy function */
$provide.decorator('ngNonBindableDirective', ["$delegate", delegator]);
}
/* Inject the provider and the delegator methods with services */
provider['$inject'] = ['$provide'];
delegator['$inject'] = ['$delegate'];
/* Inject the module with the new provider */
angular.module('nonBindableExample', []);
angular.module("nonBindableExample").config(["$provide",provider]);
</script>
<div>{{$id}}</div><div ng-non-bindable class="{{$id}}">{{$id}}</div></div>
</body>
当在单个 DOM 元素上定义了多个指令时,有时需要指定应用指令的顺序。优先级用于在调用指令编译函数之前对指令进行排序。优先级定义为数字。首先编译具有更高数字优先级的指令。链接前函数也按优先级顺序运行,但链接后函数以相反的顺序运行。具有相同优先级的指令的顺序是不确定的。默认优先级为 0。
或者简单地通过<script type="text/ng-template">
分离用户内容:
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!--Declare module-->
<script>
angular.module('foo', []);
</script>
<!--Auto Bootstrapping-->
<div ng-app="foo">
<!--Inline Template-->
<script type="text/ng-template" id="baz">
<span ng-non-bindable>Hi {{bar}}</span>
</script>
<!--data binding-->
<a href="" ng-init="bar=1" ng-class="{{bar}}" ng-include="'baz'"></a>
</div>
将 ng-include
指令与 a
元素一起使用,并将 span
元素与 ng-non-bindable
指令分离,以将文本与元素分离。
引用
- 角度:有选择地编译模板
- AngularJS标准指令优先级列表
- Dart Docs: NgNonBindableDirective class
- AngularJS Docs: search-data.json
- AngularJS API:$compile - 优先级 在
- Angular 中装饰核心指令
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!--Declare module-->
<script>
angular.module('foo', []);
</script>
<!--Auto Bootstrapping-->
<div ng-app="foo">
<!--Inline Template-->
<script type="text/ng-template" id="baz">
<span ng-non-bindable>Hi {{bar}}</span>
</script>
<!--data binding-->
<a href="" ng-init="bar=1" ng-class="{{bar}}" ng-include="'baz'"></a>
</div>