Với ng-bind-html-không an toàn bị xóa, làm cách nào để tôi thêm HTML?


265

Tôi đang cố gắng sử dụng $sanitizenhà cung cấp và ng-bind-htm-unsafechỉ thị để cho phép bộ điều khiển của tôi đưa HTML vào DIV.

Tuy nhiên, tôi không thể làm cho nó hoạt động.

<div ng-bind-html-unsafe="{{preview_data.preview.embed.html}}"></div>

Tôi phát hiện ra rằng đó là vì nó đã bị xóa khỏi AngularJS (cảm ơn).

Nhưng không có ng-bind-html-unsafe, tôi nhận được lỗi này:

http://errors.angularjs.org/undained/$sce/unsafe


Có một giải pháp đơn giản cho 1,2,23+, xem bài đăng
John Henckel

Câu trả lời:


123
  1. Bạn cần đảm bảo rằng sanitize.js đã được tải. Ví dụ: tải nó từ https://ajax.googleapis.com/ajax/libs/angularjs/[LAST_VERSION[/angular-sanitize.min.js
  2. bạn cần bao gồm ngSanitizemô-đun trên app ví dụ:var app = angular.module('myApp', ['ngSanitize']);
  3. bạn chỉ cần liên kết với nội dung ng-bind-htmlban đầu html. Không cần phải làm bất cứ điều gì khác trong bộ điều khiển của bạn. Việc phân tích cú pháp và chuyển đổi được tự động thực hiện bởi ngBindHtmlchỉ thị. (Đọc How does it workphần này: $ sce ). Vì vậy, trong trường hợp của bạn <div ng-bind-html="preview_data.preview.embed.html"></div>sẽ làm việc.

3
Đó là lựa chọn sạch nhất để làm điều đó một cách an toàn. Nó đi kèm với nhiều phụ thuộc hơn nhưng đó là về sự an toàn nên không do dự!
Pierre Maoui

Sử dụng tính năng này với ionic 1.0.0-beta.13
jasonflaherty

3
Điều này không hoạt động với một số thẻ, như đầu vào. Tất nhiên không có cách nào dễ dàng để khắc phục điều này. Thực sự bực bội.
Casey

Cách phổ biến và an toàn nhất. Thích điều này nếu bạn sẽ lập kế hoạch sử dụng bind-html trong các khung nhìn khác nhau.
eduardobursa

350

Thay vì khai báo một hàm trong phạm vi của bạn, như được đề xuất bởi Alex, bạn có thể chuyển đổi nó thành một bộ lọc đơn giản:

angular.module('myApp')
    .filter('to_trusted', ['$sce', function($sce){
        return function(text) {
            return $sce.trustAsHtml(text);
        };
    }]);

Sau đó, bạn có thể sử dụng nó như thế này:

<div ng-bind-html="preview_data.preview.embed.html | to_trusted"></div>

Và đây là một ví dụ hoạt động: http://jsfiddle.net/leeroy/6j4Lg/1/


3
Tôi có một bộ sưu tập nhỏ các công cụ hữu ích cho góc cạnh trên github , tôi sẽ đưa bộ lọc này vào các công cụ đó nếu bạn không phiền. Đây là IMHO giải pháp tốt nhất khi bạn tin tưởng html.
Capaj

@Capaj Không có vấn đề gì, nhưng nếu bạn thêm một liên kết đến câu trả lời này thì điều này sẽ được đánh giá rất cao. :-) stackoverflow.com/a/21254635
Leeroy Brun

Rất đẹp. điều này hoạt động như một sự quyến rũ trên lặp đi lặp lại lồng nhau!
Jelle Verzijden

Đây có vẻ là một giải pháp tốt hơn nhiều so với mã hóa cho mỗi bộ điều khiển. Chỉ cần một bộ lọc nhanh chóng và thực hiện! Tôi đã sử dụng nó với việc lặp lại các hàng của bảng, đơn giản như chiếc bánh .... <td ng-bind-html="representative.primary | to_trusted"></td>
Phil Nicholas

2
angular.module ('myApp'). bộ lọc ('trustAsHtml', ['$ sce', function ($ sce) {return $ sce.trustAsHtml}]);
bradw2k

275

Bạn đã chỉ ra rằng bạn đang sử dụng Angular 1.2.0 ... là một trong những ý kiến ​​khác được chỉ ra, ng-bind-html-unsafeđã không được chấp nhận.

Thay vào đó, bạn sẽ muốn làm một cái gì đó như thế này:

<div ng-bind-html="preview_data.preview.embed.htmlSafe"></div>

Trong bộ điều khiển của bạn, tiêm $scedịch vụ và đánh dấu HTML là "đáng tin cậy":

myApp.controller('myCtrl', ['$scope', '$sce', function($scope, $sce) {
  // ...
  $scope.preview_data.preview.embed.htmlSafe = 
     $sce.trustAsHtml(preview_data.preview.embed.html);
}

Lưu ý rằng bạn sẽ muốn sử dụng 1.2.0-rc3 hoặc mới hơn. (Họ đã sửa một lỗi trong RC3 khiến "người theo dõi" không thể hoạt động chính xác trên HTML đáng tin cậy.)


2
Tôi đã thử sử dụng ở trên nhưng nó phá vỡ mã của tôi. Có vẻ bạn cần phải thêm '$ scope' trước định nghĩa hàm - có lẽ nó đã được "hiểu" cùng một lúc, nhưng không còn nữa. Sau đây nên hoạt động:myApp.controller('myCtrl', ['$scope', '$sce', function($scope, $sce) {
Dexygen

4
Bạn có thể xem thêm thông tin về $ sce ở đây chỉ để theo đuổi sự tò mò! ;)
tháng

5
Lưu ý rằng điều này có thể sẽ gây ra sự cố bảo mật XSS trong mã của bạn. Xem câu trả lời gợi ý ngSanitizebên dưới ( stackoverflow.com/a/25679834/22227 ) để biết cách khắc phục an toàn hơn.
Martin Probst

Tại sao đây là một ý tưởng tồi: docs.google.com/presentation/d/
Kẻ

trustAsHtmlthực hiện những gì nó nói, nó tin tưởng bất kỳ mã html nào đến, điều này có thể dẫn đến các cuộc tấn công Cross-Site Scripting (XSS)
Aleksey Solovey

112

Đối với tôi, giải pháp đơn giản và linh hoạt nhất là:

<div ng-bind-html="to_trusted(preview_data.preview.embed.html)"></div>

Và thêm chức năng vào bộ điều khiển của bạn:

$scope.to_trusted = function(html_code) {
    return $sce.trustAsHtml(html_code);
}

Đừng quên thêm $scevào khởi tạo bộ điều khiển của bạn.


Có vẻ đơn giản hơn khi bộ điều khiển trả về html đáng tin cậy trong phạm vi $
meffect

1
Điều này có thể ném vòng lặp vô hạn vào $ sce, làm một cái gì đó như: $ scope.trusty = {}; $ scope.to_trusty = function (html_code) {return $ scope.trusty [html_code] || ($ scope.trusty [html_code] = $ sce.trustAsHtml (html_code)); };
AO_

1
Mọi giải pháp liên quan đến việc ban phước cho HTML khi được tin cậy đều giới thiệu lỗ hổng XSS. Vui lòng xem câu trả lời gợi ý ngSanitize bên dưới (stackoverflow.com/a/25679834/22227) để khắc phục an toàn hơn.
Michele Spagnuolo

65

Theo tôi, giải pháp tốt nhất cho vấn đề này là:

  1. Tạo một bộ lọc tùy chỉnh có thể có trong tệp common.module.js - được sử dụng thông qua ứng dụng của bạn:

    var app = angular.module('common.module', []);
    
    // html filter (render text as html)
    app.filter('html', ['$sce', function ($sce) { 
        return function (text) {
            return $sce.trustAsHtml(text);
        };    
    }])
  2. Sử dụng:

    <span ng-bind-html="yourDataValue | html"></span>

Bây giờ - tôi không hiểu tại sao lệnh ng-bind-htmlkhông phải trustAsHtmllà một phần của chức năng của nó - có vẻ hơi khó hiểu với tôi rằng nó không

Dù sao đi nữa - đó là cách tôi làm - 67% thời gian, nó hoạt động mọi lúc.


Bạn có thể sử dụng biểu thức chính sau để thực hiện tìm và thay thế: regex: ng-bind-html-unsafe = "((? :(?!").) *) "Thay thế: ng-bind-html =" ($ 1) | html "với bộ lọc trên.
George Donev

2
Mọi giải pháp liên quan đến việc ban phước cho HTML khi được tin cậy đều giới thiệu lỗ hổng XSS. Vui lòng xem câu trả lời gợi ý ngSanitize bên dưới (stackoverflow.com/a/25679834/22227) để khắc phục an toàn hơn.
Michele Spagnuolo

7

Bạn có thể tạo ràng buộc html không an toàn đơn giản của riêng bạn, tất nhiên nếu bạn sử dụng đầu vào của người dùng thì đó có thể là một rủi ro bảo mật.

App.directive('simpleHtml', function() {
  return function(scope, element, attr) {
    scope.$watch(attr.simpleHtml, function (value) {
      element.html(scope.$eval(attr.simpleHtml));
    })
  };
})

Không thể chỉ thị này cũng sử dụng $sce.trustAsHtml?
kontur

5

Bạn không cần sử dụng {{}} bên trong ng-bind-html-không an toàn:

<div ng-bind-html-unsafe="preview_data.preview.embed.html"></div>

Dưới đây là một ví dụ: http://plnkr.co/edit/R7JmGIo4xcJoBc1v4iki?p=preview

Toán tử {{}} về cơ bản chỉ là một tốc ký cho ng-bind, vì vậy những gì bạn đã cố gắng tạo ra một ràng buộc bên trong một ràng buộc, không hoạt động.


Tuy nhiên, nếu tôi loại bỏ nó, tôi không được tiêm gì. Và các tài liệu rất khó hiểu, sử dụng một tài liệu} docs-angularjs-org-dev.appspot.com/api/ Kẻ
metalaureate

Rất kỳ quặc. Tôi vừa mới thử nó để chắc chắn và đối với tôi nó hoạt động như mong đợi. Tôi đồng ý rằng {} là một chút khó hiểu trong các tài liệu, nhưng chúng có nghĩa là một đại diện của một biểu thức, không phải là chữ trong chuỗi. Tôi đã cập nhật câu trả lời của tôi với một plunk làm việc.
fax

Ngoài ra, nếu bạn đang sử dụng 1.2.0, hãy xem các nhận xét ở đây vì ng-bind-html-không an toàn đã bị xóa: docs.angularjs.org/api/ng.directive:ngBindHtml
ksimons 16/10/13

2
Tôi đang sử dụng 1.2. :( Grrr! Làm thế nào một người có thể tiêm HTML không an toàn? Tôi gặp lỗi này mà không có lỗi: lỗi.angularjs.org / undained /$sce /unsafe
metalaureate

Các {{}}nhà điều hành đã gây ra vấn đề của tôi với ràng buộc thất bại, cảm ơn cho gợi ý!
Campbeln

2

Tôi đã có một vấn đề tương tự. Vẫn không thể lấy nội dung từ các tệp markdown của tôi được lưu trữ trên github.

Sau khi thiết lập danh sách trắng (có thêm tên miền github) vào $ sceDelegateProvider trong app.js, nó hoạt động như một bùa mê.

Mô tả: Sử dụng danh sách trắng thay vì gói như tin cậy nếu bạn tải nội dung từ một url khác.

Tài liệu: $ sceDelegateProviderngInclude (để tìm nạp, biên dịch và bao gồm cả đoạn HTML bên ngoài)


2

Hoàn toàn thoát khỏi bối cảnh có thể bị vô hiệu hóa hoàn toàn, cho phép bạn tiêm html bằng cách sử dụng ng-html-bind. Đây là một tùy chọn không an toàn, nhưng hữu ích khi thử nghiệm.

Ví dụ từ tài liệu AngularJS về$sce :

angular.module('myAppWithSceDisabledmyApp', []).config(function($sceProvider) {
  // Completely disable SCE.  For demonstration purposes only!
  // Do not use in new projects.
  $sceProvider.enabled(false);
});

Đính kèm phần cấu hình ở trên vào ứng dụng của bạn sẽ cho phép bạn đưa html vào ng-html-bind, nhưng như tài liệu nhận xét:

SCE cung cấp cho bạn rất nhiều lợi ích bảo mật cho ít chi phí mã hóa. Sẽ khó khăn hơn nhiều khi lấy một ứng dụng bị vô hiệu hóa SCE và tự bảo mật nó hoặc bật SCE ở giai đoạn sau. Có thể có ý nghĩa để vô hiệu hóa SCE trong trường hợp bạn có nhiều mã hiện có được viết trước khi SCE được giới thiệu và bạn đang di chuyển chúng một mô-đun tại một thời điểm.


Tốt để biết về, nhưng chắc chắn một cái gì đó nên được xử lý cẩn thận.
iconoclast

2

Bạn có thể sử dụng bộ lọc như thế này

angular.module('app').filter('trustAs', ['$sce', 
    function($sce) {
        return function (input, type) {
            if (typeof input === "string") {
                return $sce.trustAs(type || 'html', input);
            }
            console.log("trustAs filter. Error. input isn't a string");
            return "";
        };
    }
]);

sử dụng

<div ng-bind-html="myData | trustAs"></div>

nó có thể được sử dụng cho các loại tài nguyên khác, ví dụ liên kết nguồn cho iframe và các loại khác được khai báo ở đây

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.