【问题标题】:ng-non-bindable only for the content of the elementng-non-bindable 仅用于元素的内容
【发布时间】:2016-02-02 23:48:58
【问题描述】:

在我们的 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-class 将不起作用。 我能看到的唯一解决方案是在其中插入另一个 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(或变体)表示“不绑定内容,否则将此元素视为正常”。

【问题讨论】:

  • 你不能摆脱 ng-class 吗?如我所见,您并没有真正评估那里的任何角度模型。
  • 嗯,你是对的,我没有真正解释问题:) 如果用户或攻击者将 Angular 绑定表达式放入用户内容中(比如 {{User.Password}}),那么 Angular会评估它,打开一个安全漏洞——一种 XSS 攻击。
  • 嗯,我看到这里讨论了类似的东西:github.com/angular/angular.js/issues/5601
  • 是的,建议就是这样,我们不应该混淆客户端和服务器代码。如果您知道@site.vaue.id 是一个服务器内容并且您的类确实依赖于它,只需编写一个普通的 JS 函数并将其放在类属性中。不要使用 ng 类。类似 class="isSiteSelected(@site.value.ID)。希望对您有所帮助
  • 对于初学者来说,以任何形式将用户密码传输到前端是没有问题的。但希望这只是一个人为的例子,而不是你的应用程序中实际发生的事情。

标签: angularjs angularjs-directive semantic-markup angularjs-bindings


【解决方案1】:

如果用户或攻击者将 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。

或者简单地通过&lt;script type="text/ng-template"&gt;分隔用户内容:

<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 指令一起使用以将文本与元素分离。

参考文献

【讨论】:

    猜你喜欢
    • 2017-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-28
    • 2013-06-11
    • 1970-01-01
    相关资源
    最近更新 更多