Улучшить эту документацию Просмотреть исходный код $sce
- $sceProvider
- служба в модуле ng
Обзор
$sce — это сервис, который предоставляет услуги строгого контекстного экранирования для AngularJS.
Строгое контекстное экранирование
Строгое контекстное экранирование (SCE) — это режим, в котором AngularJS ограничивает привязки отображением только надёжных значений. Его цель — помочь в написании кода, который (а) по умолчанию безопасен, и (б) упрощает аудит на предмет таких уязвимостей, как XSS, кликджекинг и т. д.
Обзор
Для систематического блокирования ошибок XSS, AngularJS по умолчанию рассматривает все значения как ненадежные в HTML или чувствительных URL-привязках. При привязке ненадежных значений AngularJS автоматически выполнит проверки безопасности (санитария, надёжные URL-ресурсы в зависимости от контекста) или выбросит исключение, если не может гарантировать безопасность результата. Это поведение сильно зависит от контекста: HTML может быть отфильтрован, но URL шаблонов — нет, например.
Для иллюстрации рассмотрим директиву ng-bind-html. Она отображает своё значение напрямую как HTML: мы называем это контекстом. При получении ненадежного входного значения AngularJS попытается отфильтровать его перед отображением, если доступен фильтрующий механизм, и в противном случае выбросит исключение. Чтобы обойти фильтрование и отобразить входное значение как есть, необходимо пометить его как надёжное для этого контекста перед попыткой привязки.
Начиная с версии 1.2, AngularJS по умолчанию использует SCE.
На практике
Вот пример привязки в привилегированном контексте:
<input ng-model="userHtml" aria-label="User input"> <div ng-bind-html="userHtml"></div>
Обратите внимание, что ng-bind-html привязано к userHtml, контролируемому пользователем. При отключённом SCE данное приложение позволяет пользователю отображать произвольный HTML в DIV, что является ошибкой XSS. В более реалистичном примере можно отображать комментарии пользователей, статьи блога и т.д. с помощью привязок. (HTML — лишь один пример контекста, где отображение значения, контролируемого пользователем, создаёт уязвимости безопасности.)
В случае с HTML можно использовать библиотеку, либо на стороне клиента, либо на стороне сервера, для очистки небезопасного HTML перед привязкой к значению и отображением его в документе.
Как убедиться, что каждый элемент, использующий такие привязки, связан со значением, очищенным вашей библиотекой (или возвращённым как безопасное для отображения вашим сервером)? Как убедиться, что вы случайно не удалили строку, очищающую значение, или не переименовали некоторые свойства/поля и не забыли обновить привязку к очищенному значению?
Для обеспечения безопасности по умолчанию AngularJS гарантирует, что привязки проходят через этот процесс очистки или аналогичный процесс проверки, если нет веской причины доверять данному значению в данном контексте. Это доверие формализуется вызовом функции. Это означает, что как разработчик, вы можете считать все ненадежные привязки безопасными. Затем, чтобы проанализировать ваш код на предмет проблем с безопасностью привязки, вам нужно только убедиться, что значения, которые вы помечаете как надёжные, действительно безопасны — поскольку они получены от вашего сервера, очищены вашей библиотекой и т.д. Вы можете организовать свою базу кода, чтобы помочь с этим — возможно, позволяя выполнять такие действия только файлам в определённом каталоге. Убедиться, что внутренний API, предоставляемый этим кодом, не помечает произвольные значения как надёжные, становится более управляемой задачей.
В случае с сервисом SCE AngularJS использует $sce.trustAs (и сокращённые методы, такие как $sce.trustAsHtml и т.д.) для создания надёжных версий ваших значений.
Как это работает?
В привилегированных контекстах директивы и код будут привязаны к результату $sce.getTrusted(context, value), а не непосредственно к значению. Представьте эту функцию как способ принудительно установить необходимый контекст безопасности в ваших данных. Директивы используют $sce.parseAs, а не $parse для отслеживания привязок атрибутов, которая выполняет $sce.getTrusted в фоновом режиме для неконстантных литералов. Также при привязке без директив AngularJS автоматически определит контекст ваших привязок.
Например, 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, заданным директивами директивами.
По умолчанию AngularJS загружает шаблоны только с того же домена и протокола, что и документ приложения. Это делается путём вызова $sce.getTrustedResourceUrl для URL шаблона. Чтобы загрузить шаблоны с других доменов и/или протоколов, вы можете либо добавить их в trustedResourceUrlList, либо обернуть их в надёжные значения.
Обратите внимание: политика браузера Политики одного источника и политика совместного использования ресурсов из разных источников (CORS) применяются дополнительно и могут дополнительно ограничивать успешную загрузку шаблона. Это означает, что без соответствующей политики CORS загрузка шаблонов с другого домена не будет работать во всех браузерах. Также загрузка шаблонов с file:// URL не работает в некоторых браузерах.
Это кажется излишней нагрузкой
Важно помнить, что SCE применяется только к выражениям интерполяции.
Если ваши выражения являются константными литералами, они автоматически считаются надёжными и вам не нужно вызывать $sce.trustAs на них (например, <div ng-bind-html="'<b>implicitly trusted</b>'"></div>) просто работает (не забудьте включить модуль ngSanitize). $sceDelegate также будет использовать сервис $sanitize, если он доступен при привязке ненадежных значений к контексту $sce.HTML. AngularJS предоставляет реализацию в angular-sanitize.js, и если вы хотите её использовать, вам также необходимо добавить зависимость от модуля ngSanitize в ваше приложение.
Включённый $sceDelegate поставляется с разумными значениями по умолчанию, позволяющими вам загружать шаблоны из домена вашего приложения, без необходимости даже знать о SCE. Он блокирует загрузку шаблонов с других доменов или загрузку шаблонов по протоколу http из документа, предоставленного по протоколу https. Вы можете изменить эти параметры, задав свой собственный пользовательский список надёжных URL-ресурсов и список запрещённых URL-ресурсов для соответствия таким URL.
Это значительно снижает нагрузку. Гораздо проще заплатить небольшую нагрузку и иметь приложение, которое безопасно и может быть проверено на безопасность намного проще, чем добавлять безопасность в приложение позже.
Какие типы надёжных контекстов поддерживаются?
| Контекст | Примечания |
|---|---|
$sce.HTML | Для HTML, который безопасно подключать к приложению. Директива ngBindHtml использует этот контекст для привязок. Если встречается небезопасное значение, и модуль $sanitize присутствует, он отфильтрует значение вместо вывода ошибки. |
$sce.CSS | Для CSS, который безопасно подключать к приложению. В настоящее время не используется. Вы можете использовать его в собственных директивах. |
$sce.MEDIA_URL | Для URL, которые безопасно отображать как медиа. Автоматически преобразуется из строки путём очистки при необходимости. |
$sce.URL | Для URL, которые безопасно использовать как ссылки. Автоматически преобразуется из строки путём очистки при необходимости. Обратите внимание, что $sce.URL делает более сильное утверждение об URL, чем $sce.MEDIA_URL и, следовательно, контексты, требующие надёжных значений для $sce.URL, могут использоваться где угодно, где требуются значения, надёжные для $sce.MEDIA_URL. |
$sce.RESOURCE_URL | Для URL, которые не только безопасны для использования в качестве ссылок, но и содержимое которых безопасно включать в ваше приложение. Примеры включают ng-include, src / ngSrc привязки для тегов, отличных от IMG (например, IFRAME, OBJECT, и т.д.) Обратите внимание, что $sce.RESOURCE_URL делает более сильное утверждение об URL, чем $sce.URL или $sce.MEDIA_URL и, следовательно, контексты, требующие надёжных значений для $sce.RESOURCE_URL, могут использоваться где угодно, где требуются значения, надёжные для $sce.URL или $sce.MEDIA_URL. $sceDelegateProvider#trustedResourceUrlList() и $sceDelegateProvider#bannedResourceUrlList() можно использовать для ограничения надёжных источников для RESOURCE_URL |
$sce.JS | Для JavaScript, который безопасно выполнять в контексте вашего приложения. В настоящее время не используется. Вы можете использовать его в собственных директивах. |
a[href] и img[src] очищали интерполированные значения напрямую, а не полагались на $sce.getTrusted. Начиная с 1.7.0, это больше не так. Теперь такие интерполяции отмечаются как требующие $sce.URL (для a[href]) или $sce.MEDIA_URL (для img[src]), чтобы очистка происходила (через $sce.getTrusted...) при оценке выражений сервисом $interpolate. В настоящее время в AngularJS нет привязок контекстов CSS или JS, поэтому соответствующие функции $sce.trustAs пока не нужны. Возможно, это изменится.
Формат элементов в trustedResourceUrlList/bannedResourceUrlList
Каждый элемент в этих массивах должен быть одним из следующих:
-
'self'
- Специальная строка
'self', может использоваться для сопоставления со всеми URL-адресами того же домена, что и документ приложения, используя тот же протокол.
- Специальная строка
-
Строка (кроме специального значения
'self')- Строка сопоставляется с полным нормализованным/абсолютным URL-адресом ресурса, который тестируется (сопоставление по подстрокам недостаточно).
- Используются ровно две последовательности подстановочных знаков -
*и**. Все остальные символы сопоставляются сами с собой. -
*: соответствует нулю или более вхождениям любого символа, кроме одного из следующих 6 символов: ':', '/', '.', '?', '&' и ';'. Это полезный подстановочный знак для сопоставления списков URL-адресов ресурсов. -
**: соответствует нулю или более вхождениям любого символа. Поэтому его не следует использовать в схеме, домене и т. п., так как он будет соответствовать слишком многим значениям. (например, http://**.example.com/ будет соответствовать http://evil.com/?ignore=.example.com/, и это, возможно, не было задумано.) Его использование в конце пути допустимо. (например, http://foo.example.com/templates/**).
-
RegExp (см. замечание ниже)
-
Замечание: Хотя регулярные выражения мощны и обеспечивают большую гибкость, их синтаксис (и все неизбежные экранирования) делает их сложнее поддерживать. Легко случайно ввести ошибку при обновлении сложного выражения (на мой взгляд, все регулярные выражения должны иметь хорошее покрытие тестами). Например, использование
.в регулярном выражении верно только в небольшом количестве случаев. Символ.в регулярном выражении, используемом при сопоставлении схемы или поддомена, может соответствовать:или литеральному.символу, что, вероятно, не было задумано. Сильно рекомендуется использовать шаблоны строк и переходить к регулярным выражениям только в крайнем случае. - Регулярное выражение должно быть экземпляром RegExp (т.е. не строкой). Оно сопоставляется со всем нормализованным/абсолютным URL-адресом тестируемого ресурса (даже когда в регулярном выражении нет кодов
^и$). Кроме того, любые флаги, присутствующие в RegExp (например, многострочный, глобальный, регистронезависимый), игнорируются. - Если вы генерируете свой 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 or libraries.
$sceProvider.enabled(false);
});
Использование
$sce();
Методы
-
isEnabled();
Возвращает булево значение, указывающее, включён ли SCE.
Возвращает
BooleanTrue, если SCE включён, false — в противном случае. Если вы хотите установить значение, вам нужно сделать это на этапе конфигурации модуля в $sceProvider.
-
parseAs(type, expression);
Преобразует выражение AngularJS expression в функцию. Это аналогично $parse и идентично, когда выражение — это буквальная константа. В противном случае оно оборачивает выражение в вызов $sce.getTrusted(type, result)
Параметры
Параметр Тип Описание type stringКонтекст SCE, в котором будет использоваться этот результат.
expression stringСтроковое выражение для компиляции.
Возвращает
function(context, locals)Функция, представляющая скомпилированное выражение:
-
context–{object}– объект, по отношению к которому вычисляются любые выражения, вложенные в строки (обычно объект области видимости). -
locals–{object=}– локальный объект контекста переменных, полезный для переопределения значений вcontext.
-
-
trustAs(type, value);
Делегирует вызов
$sceDelegate.trustAs. Таким образом, возвращает обернутый объект, представляющий ваше значение и доверие к его безопасности в заданном контексте. AngularJS затем может использовать это значение напрямую в привязках указанного защищённого контекста. Это используется в привязках дляng-bind-html,ng-include, и большинстваsrcатрибутных интерполяций. См. $sce для строгого контекстного экранирования.Параметры
Параметр Тип Описание type stringКонтекст, в котором это значение безопасно для использования, например
$sce.URL,$sce.RESOURCE_URL,$sce.HTML,$sce.JSили$sce.CSS.value *Значение, которое должно считаться надёжным.
Возвращает
*Обернутая версия значения, которая может использоваться как надёжная версия вашего
valueв указанном контексте. -
trustAsHtml(value);
Метод-псевдоним.
$sce.trustAsHtml(value)→$sceDelegate.trustAs($sce.HTML, value)Параметры
Параметр Тип Описание value *Значение, которое нужно пометить как надёжное для
$sce.HTMLконтекста.Возвращает
*Обернутая версия значения, которое можно использовать в качестве надёжной версии вашего
valueв$sce.HTMLконтексте (например,ng-bind-html). -
trustAsCss(value);
Метод-псевдоним.
$sce.trustAsCss(value)→$sceDelegate.trustAs($sce.CSS, value)Параметры
Параметр Тип Описание value *Значение, которое нужно пометить как надёжное для
$sce.CSSконтекста.Возвращает
*Обернутая версия значения, которое можно использовать в качестве надёжной версии вашего
valueв$sce.CSSконтексте. Этот контекст в настоящее время не используется, поэтому пока почти нет причин использовать эту функцию. -
trustAsUrl(value);
Метод-псевдоним.
$sce.trustAsUrl(value)→$sceDelegate.trustAs($sce.URL, value)Параметры
Параметр Тип Описание value *Значение, которое нужно пометить как надёжное для
$sce.URLконтекста.Возвращает
*Обернутая версия значения, которое можно использовать в качестве надёжной версии вашего
valueв$sce.URLконтексте. Этот контекст в настоящее время не используется, поэтому пока почти нет причин использовать эту функцию. -
trustAsResourceUrl(value);
Метод-псевдоним.
$sce.trustAsResourceUrl(value)→$sceDelegate.trustAs($sce.RESOURCE_URL, value)Параметры
Параметр Тип Описание value *Значение, которое нужно пометить как надёжное для
$sce.RESOURCE_URLконтекста.Возвращает
*Обернутая версия значения, которое можно использовать в качестве надёжной версии вашего
valueв$sce.RESOURCE_URLконтексте (URL-адреса шаблонов вng-include, большинствоsrcпривязок атрибутов и т.д.). -
trustAsJs(value);
Метод-псевдоним.
$sce.trustAsJs(value)→$sceDelegate.trustAs($sce.JS, value)Параметры
Параметр Тип Описание value *Значение, которое нужно пометить как надёжное для
$sce.JSконтекста.Возвращает
*Обернутая версия значения, которое можно использовать в качестве надёжной версии вашего
valueв$sce.JSконтексте. Этот контекст в настоящее время не используется, поэтому пока почти нет причин использовать эту функцию. -
getTrusted(type, maybeTrusted);
Делегирует вызов
$sceDelegate.getTrusted. Таким образом, принимает любой ввод и либо возвращает значение, безопасное для использования в указанном контексте, либо выбрасывает исключение. Эта функция учитывает надёжные значения, созданные функциейtrustAsи её псевдонимами, и когда контексты уместны, возвращает значение без обертки. Наконец, эта функция также может выбрасывать исключение, когда нет способа превратитьmaybeTrustedв надёжное значение (например, нет доступной или возможной санитизации).Параметры
Параметр Тип Описание type stringКонтекст, в котором это значение должно быть использовано.
maybeTrusted *Результат предыдущего вызова
$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–2020 Google, Inc.
Licensed under the Creative Commons Attribution License 3.0.
https://code.angularjs.org/1.8.2/docs/api/ng/service/$sce