Java Platform, Enterprise Edition (Java EE) 8
Учебник по Java EE

Назад Вперёд Содержание

Защита веб-приложений

Веб-приложения создаются разработчиками приложений, которые передают, продают или иным образом отдают приложение для установки в среде выполнения.

Здесь рассматриваются следующие темы:

Обзор безопасности веб-приложений

Разработчики приложений сообщают, как настроить безопасность для развёрнутого приложения, используя аннотации или дескрипторы развёртывания. Эта информация передаётся установщику, который использует её для задания разрешений методов для ролей безопасности, настройки проверки подлинности пользователя и настройки соответствующего транспортного механизма. Если разработчик приложения не определяет требования безопасности, установщик должен будет самостоятельно установить требования безопасности.

Некоторые элементы, необходимые для безопасности веб-приложения, нельзя указать в качестве аннотаций для всех типов веб-приложений. В этой главе объясняется, как защитить веб-приложения с помощью аннотаций, где это возможно. В нём объясняется, как использовать дескрипторы развёртывания, в которых нельзя использовать аннотации.

Указание ограничений безопасности

Ограничение безопасности используется для определения прав доступа к коллекции ресурсов путём их сопоставления с URL.

Если веб-приложение использует сервлет, можно выразить информацию об ограничениях безопасности с помощью аннотаций. В частности, используются аннотации @HttpConstraint и, необязательно, аннотации @HttpMethodConstraint в аннотации @ServletSecurity, чтобы указать ограничение безопасности.

Однако, если веб-приложение не использует сервлет, нужно указать элемент security-constraint в файле дескриптора развёртывания. Механизм аутентификации не может быть выражен с помощью аннотаций, поэтому, если используется любой метод аутентификации, кроме BASIC (по умолчанию), требуется дескриптор развёртывания.

Следующие подэлементы могут быть частью security-constraint.

  • Коллекция веб-ресурсов (web-resource-collection): список шаблонов URL (часть URL после имени хоста и порта, который вы хотите защитить) и операций HTTP (методы в файлах, которые соответствовать шаблону URL, который вы хотите защитить), который описывает набор ресурсов, которые должны быть защищены. Коллекции веб-ресурсов обсуждаются в Указание коллекции веб-ресурсов.

  • Ограничение авторизации (auth-constraint): указывает, должна ли использоваться аутентификация, и называет роли, авторизованные для выполнения запросов. Для получения дополнительной информации об ограничениях авторизации см. Указание ограничения авторизации.

  • Защита пользовательских данных (user-data-constraint): указывает, как данные защищены при передаче между клиентом и сервером. Защита пользовательских данных обсуждается в Указание безопасного соединения.

Указание коллекции веб-ресурсов

Коллекция веб-ресурсов состоит из следующих подэлементов.

  • web-resource-name — это имя, которое вы используете для этого ресурса. Его использование не является обязательным.

  • url-pattern используется для перечисления URI запросов, которые нужно защитить. Многие приложения имеют как незащищённые, так и защищённые ресурсы. Чтобы обеспечить неограниченный доступ к ресурсу, не настраивайте ограничение безопасности для этого конкретного URI запроса.

    URI запроса является частью URL после имени хоста и порта. Для примера предположим, что у вас есть сайт электронной коммерции с каталогом, и вы хотите, чтобы любой мог иметь доступ на просмотр, но область корзины покупок доступна только для клиентов. Вы можете настроить пути для своего веб-приложения, чтобы шаблон /cart/* был защищён, но всё остальное оставалось незащищённым. Предполагая, что приложение установлено по контекстному пути /myapp, верно следующее.

  • http-method используется, чтобы указать, какие методы должны быть защищены, а http-method-omission — исключены из защиты. HTTP-метод защищён web-resource-collection при любом из следующих обстоятельств:

    • Если в коллекции не указаны методы HTTP (это означает, что все они защищены)

    • Если коллекция специально указывает метод HTTP в подэлементе http-method

    • Если коллекция содержит один или несколько элементов http-method-omission, ни один из которых не указывает метод HTTP

Указание ограничений авторизации

Ограничение авторизации (auth-constraint) содержит элемент role-name. Вы можете использовать столько элементов role-name, сколько требуется.

Ограничение авторизации устанавливает требование для аутентификации и указывает роли, авторизованные для доступа к шаблонам URL и методам HTTP, объявленным этим ограничением безопасности. Если нет ограничений авторизации, контейнер должен принять запрос, не требуя аутентификации пользователя. Если есть ограничение авторизации, но в нём не указаны роли, контейнер не разрешит доступ к запросам ни при каких обстоятельствах. Каждое имя роли, указанное здесь, должно либо соответствовать имени роли одного из элементов security-role, определённых для этого веб-приложения, либо быть специально зарезервированным именем роли *, которое указывает все роли веб-приложения. Имена ролей чувствительны к регистру. Роли, определённые для приложения, должны быть назначены пользователям и группам, определённым на сервере, за исключением случаев, когда используется назначение принципалу и роли по умолчанию.

Для получения дополнительной информации о ролях безопасности см. Объявление ролей безопасности. Для получения информации о назначении ролей безопасности см. Назначение ролей пользователям и группам.

Для сервлета аннотации @HttpConstraint и @HttpMethodConstraint принимают элемент roleAllowed, который определяет авторизованные роли.

Указание безопасного соединения

Защита пользовательских данных (user-data-constraint в дескрипторе развёртывания) содержит подэлемент transport-guarantee. Защита пользовательских данных может использоваться для удовлетворения требования, чтобы защищённое соединение транспортного уровня, такое как HTTPS, использовалось для всех защищаемых шаблонов URL и методов HTTP, указанных в ограничении безопасности. Варианты транспортных гарантий: CONFIDENTIAL, INTEGRAL и NONE. Если ограничением безопасности указан CONFIDENTIAL или INTEGRAL, это обычно означает, что использование SSL является обязательным и применяется ко всем запросам, которые соответствуют шаблонам URL в коллекции веб-ресурсов, а не только в диалоговом окне входа в систему.

Уровень требуемой защиты определяется значением транспортной гарантии следующим образом.

  • CONFIDENTIAL, когда приложение требует передачи данных, чтобы другие объекты не могли наблюдать за содержимым передачи.

  • INTEGRAL, когда приложение требует, чтобы данные передавались между клиентом и сервером таким образом, чтобы их нельзя было изменить при передаче.

  • NONE, когда контейнер должен принимать запросы для любого соединения, включая незащищённое.

Замечание:

На практике серверы Java EE обрабатывают значения транспортных гарантий CONFIDENTIAL и INTEGRAL одинаково.

Защиту пользовательских данных удобно использовать в сочетании с аутентификациями пользователя: базовой и на основе форм. Если для метода аутентификации входа установлено значение BASIC или FORM, пароли не защищены, что означает, что пароли, отправленные между клиентом и сервером в незащищённой сессии, могут быть просмотрены и перехвачены третьими лицами. Использование защиты пользовательских данных с механизмом аутентификации пользователя может облегчить эту проблему. Настройка механизма аутентификации пользователя описана в Указание механизма аутентификации в дескрипторе развёртывания.

Чтобы гарантировать передачу данных по безопасному соединению, убедитесь, что поддержка SSL настроена для вашего сервера. Для сервера GlassFish Server поддержка SSL уже настроена.

Замечание:

После того, как вы переключитесь на SSL для сессии, вы никогда не должны принимать никакие не-SSL запросы на оставшуюся часть этой сессии. Например, сайт покупок может не использовать SSL до страницы оформления заказа, а затем он может переключиться на использование SSL, чтобы принять номер вашей карты. После переключения на SSL вы должны прекратить слушать не-SSL запросы для этой сессии. Причиной такой практики является то, что сам идентификатор сессии не был зашифрован в предыдущих сообщениях. Это не так уж плохо, когда вы только делаете покупки, но после того, как информация о кредитной карте будет сохранена в сессии, нельзя допустить, чтобы кто-либо использовал эту информацию для подделки транзакции покупки с вашей кредитной карты. Эта практика может быть легко реализована с помощью фильтра.

Указание ограничений безопасности для ресурсов

Вы можете создать ограничения безопасности для ресурсов в вашем приложении. Например, вы можете предоставить пользователям с ролью PARTNER полный доступ ко всем ресурсам по шаблону URL /acme/wholesale/ и разрешить пользователям с ролью CLIENT полный доступ ко всем ресурсам по шаблону URL /acme/retail/. Это рекомендуемый способ защиты ресурсов, если вы хотите защитить только некоторые методы HTTP, оставляя другие методы HTTP незащищёнными. Пример дескриптора развёртывания, который продемонстрировал бы эту функциональность, следующий:

<!-- SECURITY CONSTRAINT #1 -->
<security-constraint>
    <web-resource-collection>
        <web-resource-name>wholesale</web-resource-name>
        <url-pattern>/acme/wholesale/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>PARTNER</role-name>
    </auth-constraint>
    <user-data-constraint>
        <transport-guarantee>CONFIDENTIAL</transport-guarantee>
    </user-data-constraint>
</security-constraint>

<!-- SECURITY CONSTRAINT #2 -->
<security-constraint>
    <web-resource-collection>
        <web-resource-name>retail</web-resource-name>
        <url-pattern>/acme/retail/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>CLIENT</role-name>
    </auth-constraint>
    <user-data-constraint>
        <transport-guarantee>CONFIDENTIAL</transport-guarantee>
    </user-data-constraint>
</security-constraint>

Указание механизмов аутентификации

В этом разделе описываются встроенные механизмы аутентификации, определённые в спецификации сервлетов.

Замечание:

Альтернативный способ выполнения аутентификации пользователя, включая аутентификацию BASIC и FORM, заключается в использовании HttpAuthenticationMechanism, указанного в API безопасности Java EE и задокументированного в главе 53 «Использование API безопасности Java EE».

Механизм аутентификации пользователя определяет:

  • Способ, которым пользователь получает доступ к веб-контенту

  • При базовой аутентификации область, в которой пользователь будет аутентифицирован

  • С аутентификацией на основе форм, дополнительные атрибуты

Когда указан механизм аутентификации, пользователь должен пройти аутентификацию, прежде чем ему будет предоставлен доступ к любому ресурсу, который защищён ограничением безопасности. Может быть несколько ограничений безопасности, применяемых к нескольким ресурсам, но один и тот же метод аутентификации будет применяться ко всем защищённым ресурсам в приложении.

Прежде чем вы сможете аутентифицировать пользователя, у вас должна быть база данных имён пользователей, паролей и ролей, настроенных на вашем веб-сервере или сервере приложений. Информацию о настройке базы данных пользователей смотрите в разделе Управление пользователями и группами на сервере GlassFish.

Платформа Java EE поддерживает следующие механизмы аутентификации:

  • Базовая аутентификация

  • Аутентификация на основе форм

  • Дайджест аутентификации

  • Аутентификация клиента по цифровому сертификату

  • Взаимная аутентификация

В этом разделе рассматриваются базовая, основанная на формах и дайджест аутентификации. Клиентская и взаимная аутентификация обсуждаются в главе 54 «Безопасность Java EE: дополнительные темы».

Базовая аутентификация HTTP и аутентификация на основе форм не очень безопасные механизмы аутентификации. Обычная проверка подлинности отправляет имена пользователей и пароли через Интернет в виде текста в кодировке Base64. Проверка подлинности на основе форм отправляет эти данные в виде простого текста. В обоих случаях целевой сервер не аутентифицирован. Следовательно, эти формы аутентификации делают данные пользователя открытыми и уязвимыми. Если кто-то перехватит передачу, имя пользователя и пароль могут быть легко декодированы.

Тем не менее, когда безопасный транспортный механизм, такой как SSL, или безопасность на сетевом уровне, таком как протокол Internet Protocol Security (IPsec) или стратегии виртуальной частной сети (VPN), используется в сочетании с базовой или основанной на форме аутентификацией, некоторые из этих проблем могут быть смягчены. Чтобы указать безопасный транспортный механизм, используйте элементы, описанные в Указание безопасного соединения.

Базовая аутентификация HTTP

Указание базовой аутентификации HTTP требует, чтобы сервер запросил имя пользователя и пароль у веб-клиента и проверил, валидны ли имя пользователя и пароль, сравнив их с базой данных авторизованных пользователей в указанной области или области по умолчанию.

По умолчанию используется базовая аутентификация, если не указан механизм проверки подлинности.

При использовании базовой аутентификации выполняются следующие действия.

  1. Клиент запрашивает доступ к защищённому ресурсу.

  2. Веб-сервер возвращает диалоговое окно, которое запрашивает имя пользователя и пароль.

  3. Клиент отправляет имя пользователя и пароль на сервер.

  4. Сервер аутентифицирует пользователя в указанной области и, в случае успеха, возвращает запрошенный ресурс.

На рисунке 51-1 показано, что происходит при выборе базовой аутентификации HTTP.

Рисунок 51-1 Базовая аутентификация HTTP

Схема четырёх шагов в базовой аутентификации HTTP между клиентом и сервером

Аутентификация на основе форм

Аутентификация на основе форм позволяет разработчику контролировать внешний вид экранов аутентификации при входе, настраивая экран входа и страницы ошибок, которые HTTP-браузер предоставляет конечному пользователю. При объявлении проверки подлинности на основе форм выполняются следующие действия.

  1. Клиент запрашивает доступ к защищённому ресурсу.

  2. Если клиент не прошёл проверку подлинности, сервер перенаправляет клиента на страницу входа.

  3. Клиент отправляет форму входа на сервер.

  4. Сервер пытается аутентифицировать пользователя.

    • Если аутентификация успешна, субъект аутентифицированного пользователя проверяется, чтобы убедиться, что имеет роль, которая авторизована для доступа к ресурсу. Если пользователь авторизован, сервер перенаправляет клиента на ресурс, используя сохранённый путь URL.

    • Если аутентификация не удалась, клиент перенаправляется на страницу ошибки.

На рисунке 51-2 показано, что происходит при выборе аутентификации на основе форм.

Рисунок 51-2 Аутентификация на основе форм

Схема четырёх этапов аутентификации на основе форм между клиентом и сервером

Раздел Пример hello1-formauth: аутентификация на основе форм с приложением JavaServer Faces — это пример приложения, использующего аутентификацию на основе форм.

При выполнении входа на основе формы обязательно поддерживайте сессии с использованием файлов cookie или данных сессии SSL.

Чтобы аутентификация прошла надлежащим образом, атрибут action формы входа в систему всегда должен быть установлен в j_security_check. Это ограничение сделано для того, чтобы форма входа в систему работала независимо от того, для какого ресурса она предназначена, и чтобы сервер не указывал поле действия исходящей формы. Следующий фрагмент кода показывает, какой вид форма должна иметь на HTML-странице:

<form method="POST" action="j_security_check">
<input type="text" name="j_username">
<input type="password" name="j_password">
</form>

Дайджест аутентификация

Как и базовая аутентификация, дайджест аутентификация аутентифицирует пользователя на основе имени пользователя и пароля. Однако, в отличие от базовой аутентификации, дайджест аутентификация не отправляет пароли пользователей по сети. Вместо этого клиент отправляет односторонний криптографический хэш пароля и дополнительные данные. Хотя пароли не передаются по сети, дайджест аутентификация требует, чтобы эквиваленты паролей в открытом виде были доступны для контейнера аутентификации, чтобы он мог валидировать подлинность путём вычисления ожидаемого дайджеста.

Указание механизма аутентификации в дескрипторе развёртывания

Чтобы указать механизм аутентификации, используется элемент login-config. Он может содержать следующие подэлементы.

  • Подэлемент auth-method настраивает механизм аутентификации для веб-приложения. Содержимое элемента должно быть NONE, BASIC, DIGEST, FORM или CLIENT-CERT.

  • Подэлемент realm-name указывает имя области, которое следует использовать при выборе базовой аутентификации для веб-приложения.

  • Подэлемент form-login-config определяет страницы входа и ошибки, которые следует использовать, если указан вход на основе формы.

Замечание:

Другой способ указать аутентификацию на основе форм — использовать методы authenticate, login и logout для HttpServletRequest, как обсуждалось в Программная аутентификация пользователей.

При попытке получить доступ к веб-ресурсу, который защищён элементом security-constraint, веб-контейнер активирует механизм аутентификации, настроенный для этого ресурса. Механизм аутентификации определяет, как пользователю будет предложено войти в систему. Если элемент login-config присутствует, а элемент auth-method содержит значение, отличное от NONE, пользователь должен пройти аутентификацию для доступа к ресурсу. Если не указан механизм аутентификации, аутентификация пользователя не требуется.

В следующем примере показано, как объявить аутентификацию на основе форм в дескрипторе развёртывания:

<login-config>
    <auth-method>FORM</auth-method>
    <realm-name>file</realm-name>
    <form-login-config>
        <form-login-page>/login.xhtml</form-login-page>
        <form-error-page>/error.xhtml</form-error-page>
    </form-login-config>
</login-config>

Расположение страницы входа в систему и ошибок указывается относительно расположения дескриптора развёртывания. Примеры страниц входа в систему и ошибок показаны в Создание формы входа в систему и страницы ошибок.

В следующем примере показано, как объявить дайджест аутентификацию в дескрипторе развёртывания:

<login-config>
    <auth-method>DIGEST</auth-method>
</login-config>

Объявление ролей безопасности

Вы можете объявить названия ролей безопасности, используемые в веб-приложениях, используя элемент security-role дескриптора развёртывания. Используйте этот элемент, чтобы получить список всех ролей безопасности, на которые вы ссылаетесь в своём приложении.

В следующем фрагменте дескриптора развёртывания объявляются роли, которые будут использоваться в приложении с использованием элемента security-role, и указывается, какая из этих ролей авторизована для доступа к защищённым ресурсам с использованием элемента auth-constraint:

<security-constraint>
    <web-resource-collection>
        <web-resource-name>Protected Area</web-resource-name>
        <url-pattern>/security/protected/*</url-pattern>
        <http-method>PUT</http-method>
        <http-method>DELETE</http-method>
        <http-method>GET</http-method>
        <http-method>POST</http-method>
    </web-resource-collection>
    <auth-constraint>
        <role-name>manager</role-name>
    </auth-constraint>
</security-constraint>

 <!-- Security roles used by this web application -->
<security-role>
    <role-name>manager</role-name>
</security-role>
<security-role>
    <role-name>employee</role-name>
</security-role>

В этом примере элемент security-role перечисляет все роли безопасности, используемые в приложении: manager и employee. Это позволяет установщику назначить все роли, определённые в приложении, пользователям и группам, определённым на сервере GlassFish.

Элемент auth-constraint определяет роль manager, которая может обращаться к HTTP методам PUT, DELETE, GET и POST, расположенным в каталоге, указанном в элементе url-pattern (/security/protected/*).

В этой ситуации нельзя использовать аннотацию @ServletSecurity, поскольку её ограничения применяются ко всем шаблонам URL, указанным в аннотации @WebServlet.


Назад Вперёд Содержание
Логотип Oracle  Copyright © 2017, Oracle и/или её дочерних компаний. Все права защищены. Версия перевода 1.0.5 (Java EE Tutorial — русскоязычная версия)