Angular.js 中的部分 HTML 字符串转义

Partial HTML string escaping in Angular.js

本文关键字:HTML 字符串 转义 js Angular      更新时间:2023-09-26

我已经阅读了有关 angular 默认和$sce转义所有内容的方法,所以我通过过滤器使用 $sce.trustAsHtml() 将数据列入白名单(因为$sce不在服务中工作),如下所示:

<sup class="ng-binding" ng-bind-html="row|logEntry"></sup>

但问题是,我不信任HTML的某些部分。

深入了解细节 - 我有包含 HTML 的翻译,但它们中有可替换的标记/变量。所以翻译支持 HTML,但我不希望提供的标记包含 HTML。

我的过滤器logEntry内部如下所示:

var translated = $translate('Log.' + msg.context.entity_type) + '.' + msg.context.action, {
        'object_name': msg.context.object_name,
        'user': msg.context.user_name
});
return $sce.trustAsHtml(translated);

例如,我可以翻译有关userX更改文章的内容,但是如果用户名包含<script>alert('evilname')</script>,则不希望结果文本触发alert()

$translate本身并不相关,它可以是任何 HTML 字符串,我希望将某些部分替换为常规 JS .replace()内容保留为"文本"。

所以我的问题是 - 我怎样才能转义 HTML 的某些部分?我是否必须将其切成视图内的各个部分?还是我必须诉诸自定义转义(将 HTML 标记转义为 HTML 实体的最快方法?)?对于这些事情,有首选的做法吗?

让我们从重组您的logEntry开始,以分离出插值参数

var translationId = 'Log.' + msg.context.entity_type) + '.' + msg.context.action;
var interpolateParams = {
        'object_name': msg.context.object_name,
        'user': msg.context.user_name
};
var translated = $translate(translationId, interpolateParams);
return $sce.trustAsHtml(translated);

您希望从interpolateParams转义所有 HTML,但在翻译模板中保留任何 HTML。 使用此代码复制对象,循环访问其值并替换为转义的 HTML。

var safeParams = angular.copy(interpolateParams);    
angular.forEach(safeParams, function(value, key, obj) {     
  obj[key] = encodeEntities(value)
  // if you want safe/sanitized HTML, use this instead
  // obj[key] = $sanitize(value);
});
var translated = $translate(translationId, safeParams);

最后,角度的encodeEntities功能没有暴露,所以我们不得不从角度消毒中借用源代码.js

var SURROGATE_PAIR_REGEXP = /['uD800-'uDBFF]['uDC00-'uDFFF]/g,
    // Match everything outside of normal chars and " (quote character)
    NON_ALPHANUMERIC_REGEXP = /([^'#-~| |!])/g;
function encodeEntities(value) {
  return value.
    replace(/&/g, '&amp;').
    replace(SURROGATE_PAIR_REGEXP, function(value) {
      var hi = value.charCodeAt(0);
      var low = value.charCodeAt(1);
      return '&#' + (((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000) + ';';
    }).
    replace(NON_ALPHANUMERIC_REGEXP, function(value) {
      return '&#' + value.charCodeAt(0) + ';';
    }).
    replace(/</g, '&lt;').
    replace(/>/g, '&gt;');
}

更新:更新到角度平移 2.7.0 后,出现以下消息:

pascalprecht.translate.$translateSanitization:无需消毒 策略已配置。这可以有严重的安全性 影响。看 http://angular-translate.github.io/docs/#/guide/19_security 详。

Sp 而不是上面的trustlate答案,角度平移可以通过以下方式实现相同的结果:

$translateProvider.useSanitizeValueStrategy('escapeParameters');

查看文档,了解更多净化价值策略

在您的应用中添加

$translateProvider.useSanitizeValueStrategy('escapeParameters');

这样,您的代码如下所示:

myApp.config(function ($translateProvider) {
    //...whatever
  $translateProvider.useSanitizeValueStrategy('escapeParameters');
});