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

Art*_*pov 5 javascript security angularjs angular-translate

我看了一下逃逸角的方式默认一切$sce,所以我白名单的数据与$sce.trustAsHtml()通过过滤器(因为$sce没有在服务工作),就像这样:

<sup class="ng-binding" ng-bind-html="row|logEntry"></sup>
Run Code Online (Sandbox Code Playgroud)

但问题是,我不相信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);
Run Code Online (Sandbox Code Playgroud)

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

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

所以我的问题是 - 如何逃避HTML的部分内容?我是否必须在视图内部分切片?或者我是否必须采用自定义转义( 最快的方法将HTML标记转义为HTML实体?)?这种事情是否有首选做法?

Kev*_*son 5

让我们从重构你的内容开始,logEntry将interpolateParams分开

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);
Run Code Online (Sandbox Code Playgroud)

您想要从中转义所有HTML,interpolateParams但在翻译模板中保留任何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);
Run Code Online (Sandbox Code Playgroud)

最后,encodeEntitiesangular 的功能没有暴露,因此我们不得不从angular-sanitize.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;');
}
Run Code Online (Sandbox Code Playgroud)

更新:更新为angular-translate 2.7.0后出现此消息:

pascalprecht.translate.$ translateSanitization:未配置清理策略.这可能会产生严重的安全隐患.有关详细信息,请参见 http://angular-translate.github.io/docs/#/guide/19_security.

Sp代替trustlate上面的答案,angular-translate可以完成相同的结果:

$translateProvider.useSanitizeValueStrategy('escapeParameters');
Run Code Online (Sandbox Code Playgroud)

有关更多Sanitize Value Strategies的信息,请参阅文档