Улучшить эту документацию Просмотреть исходный код $sce
- $sceProvider
- Сервис в модуле ng
$sce — это сервис, предоставляющий AngularJS услуги Strict Contextual Escaping.
Строгое контекстуальное экранирование
Строгое контекстуальное экранирование (SCE) — это режим, в котором AngularJS требует, чтобы привязки в определённых контекстах возвращали значение, которое считается безопасным для использования в этом контексте. Одним из таких контекстов является привязка произвольного HTML, контролируемого пользователем через ng-bind-html. Такие контексты называются привилегированными или контекстами SCE.
Начиная с версии 1.2, Angular по умолчанию включает SCE.
Примечание: При включении (по умолчанию) IE<11 в режиме quirks mode не поддерживается. В этом режиме IE<11 позволяет выполнять произвольный JavaScript с помощью синтаксиса expression(). Обратитесь к <!doctype html> в начало своего HTML-документа.
SCE помогает писать код, который (а) по умолчанию безопасен, и (б) значительно упрощает аудит на предмет уязвимостей, таких как XSS, clickjacking и т. д.
Вот пример привязки в привилегированном контексте:
<input ng-model="userHtml" aria-label="User input"> <div ng-bind-html="userHtml"></div>
Обратите внимание, что ng-bind-html привязано к userHtml, контролируемому пользователем. Без SCE это приложение позволяет пользователю отображать произвольный HTML в DIV. В более реалистичном примере можно отображать пользовательские комментарии, статьи блога и т. д. с помощью привязок. (HTML — всего лишь один пример контекста, где отображение пользовательского ввода приводит к уязвимостям безопасности.)
В случае с HTML вы можете использовать библиотеку, либо на стороне клиента, либо на стороне сервера, для очистки небезопасного HTML перед привязкой к значению и отображением его в документе.
Как вы можете убедиться, что в каждом месте, где использовались такие привязки, значения были очищены вашей библиотекой (или возвращены как безопасные для отображения вашим сервером)? Как вы можете убедиться, что случайно не удалили строку, которая очищала значение, или не переименовали какие-либо свойства/поля и не забыли обновить привязку к очищенному значению?
Для обеспечения безопасности по умолчанию необходимо убедиться, что любые такие привязки запрещены, если вы не можете определить, что что-то явно говорит о том, что значение безопасно для привязки в данном контексте. Затем вы можете проанализировать свой код (простая команда grep подойдет) для обеспечения того, что это делается только для тех значений, безопасность которых вы можете легко определить — потому что они были получены с вашего сервера, очищены вашей библиотекой и т. д. Вы можете организовать свою кодовую базу для помощи в этом — возможно, разрешая выполнять это только в файлах определенного каталога. Обеспечение того, что внутренний API, предоставляемый этим кодом, не помечает произвольные значения как безопасные, становится более управляемой задачей.
В случае сервиса SCE AngularJS используется $sce.trustAs (и сокращённые методы, такие как $sce.trustAsHtml и т. д.) для получения значений, которые будут приняты контекстами SCE/привилегированными контекстами.
Как это работает?
В привилегированных контекстах директивы и код будут привязаны к результату $sce.getTrusted(context, value), а не непосредственно к значению. Директивы используют $sce.parseAs, а не $parse для отслеживания привязок атрибутов, что выполняет $sce.getTrusted за кулисами для неконстантных литералов.
Например, ngBindHtml использует $sce.parseAsHtml(выражение привязки). Вот фактический код (несколько упрощённый):
var ngBindHtmlDirective = ['$sce', function($sce) {
return function(scope, element, attr) {
scope.$watch($sce.parseAsHtml(attr.ngBindHtml), function(value) {
element.html(value || '');
});
};
}];
Влияние на загрузку шаблонов
Это относится как к директиве ng-include, так и к шаблонам templateUrl, указанным директивами директивами.
По умолчанию Angular загружает шаблоны только с того же домена и протокола, что и документ приложения. Это делается путём вызова $sce.getTrustedResourceUrl для URL шаблона. Для загрузки шаблонов с других доменов и/или протоколов можно либо внести их в белый список, либо обернуть их в надёжное значение.
Обратите внимание: политика браузера Same Origin Policy и политика Cross-Origin Resource Sharing (CORS) применяются дополнительно к этому и могут дополнительно ограничить успешную загрузку шаблона. Это означает, что без соответствующей политики CORS загрузка шаблонов с другого домена не будет работать во всех браузерах. Также загрузка шаблонов с file:// URL не работает в некоторых браузерах.
Это кажется слишком громоздким
Важно помнить, что SCE применяется только к выражениям интерполяции.
Если ваши выражения являются константными литералами, они автоматически считаются надёжными, и вам не нужно вызывать $sce.trustAs для них (не забудьте включить ngSanitize модуль) (например, <div ng-bind-html="'<b>implicitly trusted</b>'"></div>) просто работает.
Кроме того, a[href] и img[src] автоматически очищают свои URL-адреса и не передают их через $sce.getTrusted. SCE здесь не играет роли.
Включённый $sceDelegate поставляется с разумными значениями по умолчанию, позволяя загружать шаблоны с ng-include с домена вашего приложения, не зная о SCE. Он блокирует загрузку шаблонов с других доменов или загрузку шаблонов по протоколу HTTP из документа, обслуживаемого по протоколу HTTPS. Вы можете изменить эти настройки, задав собственные пользовательские белые списки и чёрные списки для сопоставления таких URL-адресов.
Это существенно снижает нагрузку. Гораздо проще заплатить небольшую плату за надёжность и получить приложение, которое является безопасным и может быть проверено для проверки гораздо легче, чем добавлять безопасность в приложение позже.
Какие типы надёжных контекстов поддерживаются?
| Контекст | Примечания |
|---|---|
$sce.HTML | Для HTML, который безопасно включить в приложение. Директива ngBindHtml использует этот контекст для привязок. Если обнаружится небезопасное значение, и модуль $sanitize присутствует, он очистит значение вместо того, чтобы вызывать ошибку. |
$sce.CSS | Для CSS, который безопасно включить в приложение. В настоящее время не используется. Вы можете использовать его в собственных директивах. |
$sce.URL | Для URL-адресов, которые безопасно использовать в качестве ссылок. В настоящее время не используется (<a href= и <img src= очищают свои URL-адреса и не являются контекстом SCE.) |
$sce.RESOURCE_URL | Для URL-адресов, которые не только безопасны для использования в качестве ссылок, но и содержимое которых безопасно включать в ваше приложение. Примеры включают ng-include, src / ngSrc привязки для тегов, отличных от IMG (например, IFRAME, OBJECT, и т. д.). Обратите внимание, что $sce.RESOURCE_URL делает более сильное утверждение о URL-адресе, чем $sce.URL, и поэтому контексты, требующие надёжных значений для $sce.RESOURCE_URL, могут использоваться везде, где требуются значения, надёжные для $sce.URL. |
$sce.JS | Для JavaScript-кода, который безопасно выполнить в контексте вашего приложения. В настоящее время не используется. Вы можете использовать его в собственных директивах. |
Формат элементов в resourceUrlWhitelist/Чёрном списке
Каждый элемент в этих массивах должен быть одним из следующих:
-
'self'
- Специальная строка,
'self', может быть использована для сопоставления со всеми URL-адресами того же домена, что и документ приложения, с использованием того же протокола.
- Специальная строка,
-
Строка (кроме специального значения
'self')- Строка сопоставляется с полным нормализованным/абсолютным URL-адресом ресурса, который тестируется (сопоставления по подстрокам недостаточно).
- Существует ровно две последовательности подстановочных знаков -
*и**. Все остальные символы соответствуют сами себе. -
*: соответствует нулю или более вхождениям любого символа, кроме одного из следующих 6 символов: ':', '/', '.', '?', '&' и ';'. Это полезный подстановочный знак для использования в белом списке. -
**: соответствует нулю или более вхождениям любого символа. Поэтому он не подходит для использования в схеме, домене и т. д., так как он соответствует слишком многому. (например, http://**.example.com/ будет соответствовать http://evil.com/?ignore=.example.com/, и это, возможно, не было целью.) Его использование в конце пути допустимо. (например, http://foo.example.com/templates/**).
-
RegExp (см. примечание ниже)
-
Примечание: Хотя регулярные выражения мощные и предлагают большую гибкость, их синтаксис (и все неизбежные экранирования) делает их сложнее поддерживать. Легко случайно ввести ошибку при обновлении сложного выражения (по-моему, все регулярные выражения должны иметь хорошее покрытие тестами). Например, использование
.в регулярном выражении правильно только в небольшом количестве случаев. Символ.в регулярном выражении, используемом при сопоставлении схемы или поддомена, может соответствовать:или литеральному., что, вероятно, не было задумано. Настоятельно рекомендуется использовать шаблоны строк и прибегать к регулярным выражениям только в крайнем случае. - Регулярное выражение должно быть экземпляром RegExp (т. е. не строкой). Оно сопоставляется со всем нормализованным/абсолютным URL-адресом тестируемого ресурса (даже если в регулярном выражении не было кодов
^и$). Кроме того, любые флаги, присутствующие в регулярном выражении (например, многострочный, глобальный, регистронезависимый), игнорируются. - Если вы генерируете свой JavaScript из другого шаблонизатора (не рекомендуется, например, в вопросе #4006), помните, чтобы экранировать своё регулярное выражение (и будьте осторожны, что вам может потребоваться больше одного уровня экранирования в зависимости от вашего шаблонизатора и способа интерполяции значения). Используйте механизм экранирования вашей платформы, так как он может быть достаточно хорош до написания собственного. Например, в Ruby есть Regexp.escape(str), а в Python — re.escape. В Javascript нет аналогичной встроенной функции для экранирования. Посмотрите на библиотеку Google Closure goog.string.regExpEscape(s).
-
Примечание: Хотя регулярные выражения мощные и предлагают большую гибкость, их синтаксис (и все неизбежные экранирования) делает их сложнее поддерживать. Легко случайно ввести ошибку при обновлении сложного выражения (по-моему, все регулярные выражения должны иметь хорошее покрытие тестами). Например, использование
См. $sceDelegateProvider для примера.
Покажите мне пример использования SCE.
Можно ли полностью отключить SCE?
Да, можно. Однако это настоятельно не рекомендуется. SCE предоставляет много преимуществ в плане безопасности при небольших затратах на программирование. Будет гораздо сложнее взять приложение с отключенным SCE и либо защитить его самостоятельно, либо включить SCE на более позднем этапе. Это может быть целесообразно для случаев, когда у вас много существующего кода, написанного до появления SCE, и вы переносите их по модулям.
Тем не менее, вот как вы можете полностью отключить SCE:
angular.module('myAppWithSceDisabledmyApp', []).config(function($sceProvider) {
// Completely disable SCE. For demonstration purposes only!
// Do not use in new projects.
$sceProvider.enabled(false);
});
Использование
$sce();
Методы
-
isEnabled();
Возвращает логическое значение, указывающее, включен ли SCE.
Возвращаемое значение
Booleantrue, если SCE включен, false в противном случае. Если вы хотите установить значение, необходимо сделать это во время конфигурации модуля на странице $sceProvider.
-
parseAs(type, expression);
Преобразует выражение Angular expression в функцию. Это аналогично $parse и идентично, когда выражение является литеральной константой. В противном случае, оно оборачивает выражение в вызов $sce.getTrusted(type, result)
Параметры
Параметр Тип Подробности type stringТип контекста SCE, в котором будет использоваться этот результат.
expression stringСтроковое выражение для компиляции.
Возвращаемое значение
function(context, locals)функция, представляющая скомпилированное выражение:
-
context–{object}– объект, относительно которого оцениваются любые выражения, встроенные в строки (обычно объект области видимости). -
locals–{object=}– объект контекста локальных переменных, полезный для переопределения значений вcontext.
-
-
trustAs(type, value);
Делегирует вызов
$sceDelegate.trustAs. Таким образом, возвращает объект, которому Angular доверяет для использования в указанных строгих контекстах экранирования (таких как ng-bind-html, ng-include, интерполяция атрибута src, интерполяция атрибутов привязки событий DOM, таких как onclick и т. д.), используя предоставленное значение. См. * $sce для включения строгого экранирования контекста.Параметры
Параметр Тип Подробности type stringТип контекста, в котором это значение безопасно для использования. Например, url, resourceUrl, html, js и css.
value *Значение, которое должно считаться надёжным/безопасным.
Возвращаемое значение
*Значение, которое может быть использовано для представления предоставленного
valueв местах, где Angular ожидает возвращаемого значения $sce.trustAs(). -
trustAsHtml(value);
Метод-синоним.
$sce.trustAsHtml(value)→$sceDelegate.trustAs($sce.HTML, value)Параметры
Параметр Тип Подробности value *Значение, которому нужно доверять.
Возвращаемое значение
*Объект, который может быть передан в $sce.getTrustedHtml(value) для получения исходного значения. (Директивы с привилегиями принимают только выражения, которые являются либо литеральными константами, либо результатом вызова $sce.trustAs.)
-
trustAsUrl(value);
Метод-синоним.
$sce.trustAsUrl(value)→$sceDelegate.trustAs($sce.URL, value)Параметры
Параметр Тип Подробности value *Значение, которому нужно доверять.
Возвращаемое значение
*Объект, который можно передать в $sce.getTrustedUrl(value) для получения исходного значения. (Директивы с привилегиями принимают только выражения, которые являются либо литеральными константами, либо результатом вызова $sce.trustAs.)
-
trustAsResourceUrl(value);
Метод-синоним.
$sce.trustAsResourceUrl(value)→$sceDelegate.trustAs($sce.RESOURCE_URL, value)Параметры
Параметр Тип Подробности value *Значение, которому нужно доверять.
Возвращаемое значение
*Объект, который можно передать в $sce.getTrustedResourceUrl(value) для получения исходного значения. (Директивы с привилегиями принимают только выражения, которые являются либо литеральными константами, либо результатом вызова $sce.trustAs.)
-
trustAsJs(value);
Метод-синоним.
$sce.trustAsJs(value)→$sceDelegate.trustAs($sce.JS, value)Параметры
Параметр Тип Подробности value *Значение, которому нужно доверять.
Возвращаемое значение
*Объект, который можно передать в $sce.getTrustedJs(value) для получения исходного значения. (Директивы с привилегиями принимают только выражения, которые являются либо литеральными константами, либо результатом вызова $sce.trustAs.)
-
getTrusted(type, maybeTrusted);
Делегирует вызов
$sceDelegate.getTrusted. Таким образом, принимает результат вызова$sce.trustAs() и возвращает исходное значение, если тип запрошенного контекста является супертипом созданного типа. Если это условие не выполняется, выбрасывается исключение.Параметры
Параметр Тип Подробности type stringТип контекста, в котором будет использоваться это значение.
maybeTrusted *Результат предыдущего вызова
$sce.trustAs.Возвращаемое значение
*Значение, которое было изначально предоставлено
$sce.trustAs, если оно допустимо в этом контексте. В противном случае выбрасывается исключение. -
getTrustedHtml(value);
Метод-синоним.
$sce.getTrustedHtml(value)→$sceDelegate.getTrusted($sce.HTML, value)Параметры
Параметр Тип Подробности value *Значение для передачи в
$sce.getTrusted.Возвращаемое значение
*Возвращаемое значение
$sce.getTrusted($sce.HTML, value) -
getTrustedCss(value);
Метод-синоним.
$sce.getTrustedCss(value)→$sceDelegate.getTrusted($sce.CSS, value)Параметры
Параметр Тип Подробности value *Значение для передачи в
$sce.getTrusted.Возвращаемое значение
*Возвращаемое значение
$sce.getTrusted($sce.CSS, value) -
getTrustedUrl(value);
Метод-синоним.
$sce.getTrustedUrl(value)→$sceDelegate.getTrusted($sce.URL, value)Параметры
Параметр Тип Подробности value *Значение для передачи в
$sce.getTrusted.Возвращаемое значение
*Возвращаемое значение
$sce.getTrusted($sce.URL, value) -
getTrustedResourceUrl(value);
Метод-синоним.
$sce.getTrustedResourceUrl(value)→$sceDelegate.getTrusted($sce.RESOURCE_URL, value)Параметры
Параметр Тип Подробности value *Значение для передачи в
$sceDelegate.getTrusted.Возвращаемое значение
*Возвращаемое значение
$sce.getTrusted($sce.RESOURCE_URL, value) -
getTrustedJs(value);
Метод-синоним.
$sce.getTrustedJs(value)→$sceDelegate.getTrusted($sce.JS, value)Параметры
Параметр Тип Подробности value *Значение для передачи в
$sce.getTrusted.Возвращаемое значение
*Возвращаемое значение
$sce.getTrusted($sce.JS, value)
-
parseAsHtml(expression);
Метод сокращенного синтаксиса.
$sce.parseAsHtml(expression string)→$sce.parseAs($sce.HTML, value)Параметры
Параметр Тип Подробности expression stringСтроковое выражение для компиляции.
Возвращаемое значение
function(context, locals)Функция, представляющая скомпилированное выражение:
-
context–{object}– объект, по отношению к которому оцениваются любые выражения, встроенные в строки (обычно объект области видимости). -
locals–{object=}– объект контекста локальных переменных, полезный для переопределения значений вcontext.
-
-
parseAsCss(expression);
Метод сокращенного синтаксиса.
$sce.parseAsCss(value)→$sce.parseAs($sce.CSS, value)Параметры
Параметр Тип Подробности expression stringСтроковое выражение для компиляции.
Возвращаемое значение
function(context, locals)Функция, представляющая скомпилированное выражение:
-
context–{object}– объект, по отношению к которому оцениваются любые выражения, встроенные в строки (обычно объект области видимости). -
locals–{object=}– объект контекста локальных переменных, полезный для переопределения значений вcontext.
-
-
parseAsUrl(expression);
Метод сокращенного синтаксиса.
$sce.parseAsUrl(value)→$sce.parseAs($sce.URL, value)Параметры
Параметр Тип Подробности expression stringСтроковое выражение для компиляции.
Возвращаемое значение
function(context, locals)Функция, представляющая скомпилированное выражение:
-
context–{object}– объект, по отношению к которому оцениваются любые выражения, встроенные в строки (обычно объект области видимости). -
locals–{object=}– объект контекста локальных переменных, полезный для переопределения значений вcontext.
-
-
parseAsResourceUrl(expression);
Метод сокращенного синтаксиса.
$sce.parseAsResourceUrl(value)→$sce.parseAs($sce.RESOURCE_URL, value)Параметры
Параметр Тип Подробности expression stringСтроковое выражение для компиляции.
Возвращаемое значение
function(context, locals)Функция, представляющая скомпилированное выражение:
-
context–{object}– объект, по отношению к которому оцениваются любые выражения, встроенные в строки (обычно объект области видимости). -
locals–{object=}– объект контекста локальных переменных, полезный для переопределения значений вcontext.
-
-
parseAsJs(expression);
Метод сокращенного синтаксиса.
$sce.parseAsJs(value)→$sce.parseAs($sce.JS, value)Параметры
Параметр Тип Подробности expression stringСтроковое выражение для компиляции.
Возвращаемое значение
function(context, locals)Функция, представляющая скомпилированное выражение:
-
context–{object}– объект, по отношению к которому оцениваются любые выражения, встроенные в строки (обычно объект области видимости). -
locals–{object=}– объект контекста локальных переменных, полезный для переопределения значений вcontext.
-
© 2010–2017 Google, Inc.
Licensed under the Creative Commons Attribution License 4.0.
https://code.angularjs.org/1.4.14/docs/api/ng/service/$sce