Angular 1.2:ng-bind-html删除img上的src属性

时间:2013-09-27 09:24:11

标签: angularjs tinymce xss

我在客户端使用Angular(1.2 RC2)开发CMS驱动的网站。由于内容来自CMS,我不幸被迫在JSON字符串中使用接收HTML。大多数HTML都被注入并渲染得很好,但是图像标签的src被剥离了。根据我的阅读,src应该以“unsafe:”为前缀,如果这是Angular中的XSS安全问题,则不会完全删除..但我可能会弄错。

我已经有一段时间处于这个问题,感觉我已经尝试了从合理到彻头彻尾的愚蠢的一切。将我的CMS网址列入白名单,将所有内容列入白名单,禁用 $ sce ,强制html通过 $ sce.trustAsHtml()并且好......到目前为止,没有运气。由于该网站是CMS驱动的,我不幸的是不能创造一个吸引人/小提琴,但我希望一个善良的灵魂无论如何都会试图提供帮助。

更新:忘记提及我也尝试了 ng-src ,效果相同。 更新II :如果我使用HTTPS,则会保留src属性并显示图像。这是可以接受的,因为它将在生产中运行HTTPS,但我仍然想知道为什么禁用$ sce不起作用。

浏览器看到的HTML (slide.body的内容)

<div class="row">
    <div class="col-md-6 visible-md visible-lg">
        <img alt="none" class="img-responsive">
    </div>
    <div class="col-xs-12 col-md-6">
        <div class="itx-article-header">
             <h1>Sulvat Quis 1</h1>

             <h2>– Nullam dictum ac enim</h2>

        </div>
        <p>Proin quis justo vel felis varius sodales sit amet ut diam.</p>
    </div>
</div>

JADE(HTML)

.my-carousel(ng-controller='CarouselCtrl')
    carousel(interval='myInterval')
        slide(ng-repeat='slide in slides', active='slide.active')
            .my-carousel-item(ng-bind-html='slide.body')

角度控制器

.controller('CarouselCtrl', ['$sce', 'Article', '$scope',
    function($sce, Article, $scope) {
        $scope.myInterval = -1;
        $scope.slides = Article.query(
            {category: 'carousel'},
            function(data){
                for (var i = 0; i < data.length; i++) {
                    $scope.slides[i].body = $sce.trustAsHtml(data[i].body);                     
                }
            },
            function() {
                // Fail
            });
    }])

示例JSON响应(幻灯片) 对于宽盒子感到抱歉,无法对其进行格式化。

{
"cmarId": 16,
"corp": {
    "corpId": 2,
    "guiSelected": false
},
"createdAt": "Sep 27, 2013",
"articleTag": "slide-1",
"headline": "Slide 1",
"highlighted": false,
  "body": "\u003cdiv class\u003d\"container my-carousel-container-small\"\u003e\r\n\u003cdiv class\u003d\"row\"\u003e\r\n\u003cdiv class\u003d\"col-md-6 visible-md visible-lg\"\u003e\u003cimg ng-src\u003d\"img/illustrative/laptop.jpg\" alt\u003d\"none\" class\u003d\"img-responsive\" /\u003e\u003c/div\u003e\r\n\u003cdiv class\u003d\"col-xs-12 col-md-6\"\u003e\r\n\u003cdiv class\u003d\"my-article-header\"\u003e\r\n\u003ch1\u003eSulvat Quis 1\u003c/h1\u003e\r\n\u003ch2\u003e– Nullam dictum ac enim\u003c/h2\u003e\r\n\u003c/div\u003e\r\n\u003cp\u003eProin quis justo vel felis varius sodales sit amet ut diam. Fusce auctor sapien nec purus sagittis, in venenatis turpis luctus. Nullam dictum ac enim sed commodo. Vivamus et placerat sapien.\u003c/p\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e",
"articlePriority": 0,
"category": {
    "cmcaId": 9,
    "corp": {
        "corpId": 2,
        "guiSelected": false
    },
    "name": "carousel",
    "visibleInMenu": false
},
"published": true

}

4 个答案:

答案 0 :(得分:9)

您在这里遗失的作品是通过$sce.trustAsResourceURL();信任图片网址。有关相关文档,请参阅here

编辑:此外,您似乎没有将ng-src值包装在引号中(以及它作为HTML属性所需的引号)。这不起作用 - ng-src期望一个javascript字符串作为表达式的最终结果,并且你为它提供了一个无效的javascript文字。

答案 1 :(得分:2)

参考: AngularJS documentation for $sanitize有一个演示版。在此演示中,如果您使用src代替ng-srcng-bind-html使用函数(从$sce.trustAsHtml()返回对象),则图像看起来像预期的那样。


建议修改:我首先将ng-src替换为src

然后我会改变

for (var i = 0; i < data.length; i++) {
    $scope.slides[i].body = $sce.trustAsHtml(data[i].body);                     
}

for (var i = 0; i < data.length; i++) {
    $scope.slides[i].body = function() {
        return $sce.trustAsHtml(data[i].body);
    };
}

最后,这个

.my-carousel-item(ng-bind-html='slide.body')

会改为

.my-carousel-item(ng-bind-html='slide.body()')

我自己没有对此进行测试,但如果有效,请告诉我。


编辑(2013-11-02): 错字修复 - 我在功能示例中添加了return。代码应该按预期工作。

答案 2 :(得分:2)

在AngularUI讨论中查看此评论: https://github.com/angular-ui/bootstrap/issues/813#issuecomment-25760432

这是一个重新实现AngularJS pre 1.2中存在的旧bind-html-unsafe特征的指令。最后,这将与上面提到的相同,但最小的麻烦。所以你可以使用ng-bind-html-unsafe而不是通过在主代码中添加$ sce旁路来降低代码的可读性。

另请参阅此Stackoverflow问题:How do you use $sce.trustAsHtml(string) to replicate ng-bind-html-unsafe in Angular 1.2+

答案 3 :(得分:1)

经过几个小时的搜索后,如何显示通过WYSIWYG编辑器为我的CMS应用程序上传的图像 我发现了这个

.filter('toTrusted', ['$sce', function($sce) {
    return function(text) {
        return $sce.trustAsHtml(text);
    };
}]);
<div ng-bind-html="data  | toTrusted"></div>

希望有所帮助