3 октября 2011 г.

Безопасность web-приложения

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

Аутентификация
Настройка листа пользователей, имеющих доступ к работе с приложением, зависит от контейнера, который вы используете. К примеру, для Apache Tomcat нужно модифицировать файл tomcat-users.xml, который расположен по адресу $TOMCAT/conf. Например, он может выглядеть так:
<tomcat-users>
    <role rolename=”Admin”/>
    <role rolename=”User”/>
    <user username=”root” password=”toor” roles=”Admin, User” />
    <user username=”user” password=”resu” roles=”User” />
</tomcat-users>
Имена ролей чувствительны к регистру.
Для того чтобы аутентификация работала, нужно в дескрипторе развёртывания написать:
<login-config>
    <auth-method>BASIC</auth-method>
</login-config>
И указать какие роли мы хотим использовать в приложении:
<security-role><role-name>Admin</role-name></security-role>
<security-role><role-name>User</role-name></security-role>

Авторизация на уровне контейнера
В дескрипторе развёртывания прописывается тэг <security-constraint>. Например:
<security-constraint>
    <web-resource-name>Work with clients</web-resouce-name>
    <web-resource-collection>
        <url-pattern>/Bank/AddClient/*</url-pattern>
        <url-pattern>/Bank/Credits/*</url-pattern>
        <http-method>GET</http-method>
        <http-method>POST</http-method>
    </web-resource-collection>
    <auth-constraint>
        <role-name>Admin</role-name>
        <role-name>User</role-name>
    </auth-constraint>
</security-constraint>
Этот конфиг запретит всем пользователям, которые не являются участниками групп Admin или User, обращаться через GET или POST к указанным ресурсам. Помимо GET и POST валидными методами являются PUT, TRACE, DELETE, HEAD и OPTIONS. Если не указывать <http-method>, то все методы являются защищенными. Тэг <auth-constraint> является не обязательным: если его не указато, то доступ к ресурсу будут иметь все пользователи. Этого же эффекта можно добиться просто поставив * в теле тэга.
Если в разных <security-constraint> вы укажите в <url-pattern> одинаковый путь, но в <auth-constraint> разные группы, то контейнер будет предоставлять доступ к ресурсу и для пользователей из первого и для пользователей из второго <security-constaint>.
Если указать <auth-constraint/> то никто из пользователей не сможет добраться к ресурсу. Никто, кроме самого приложения. Таким образом можно создавать части проекта, которые доступны через request dispatcher, но недоступны напрямую.

Авторизация на программном уровне
Безопасность приложения может поддерживаться на уровне приложения.
Для этого в HttpServletRequest существует 3 метода:
  • getUserPrincipal() – используется с EJB;
  • getRemoteUser() – используется чтобы проверить статус аутентификации (применяется редко);
  • isUserInRole() – используется вместо авторизации по HTTP-методам (GET, POST и т.д.)
Последний метод даёт возможность менять поведение сервлета «на лету» для пользователей, принадлежащим к определенным группам или не принадлежащим к ним.
Если вас не устраивают названия ролей контейнера приложений, то вы можете создать алиасы прописав в дескрипторе развертывания следующее:
<servlet>
    <security-role-ref>
        <role-name>Administrator</role-name>
        <role-link>Admin</role-link>
    </security-role-ref>
    …
</servlet>
Теперь вы можете использовать короткое имя Admin вместо длинного Administrator.

Типы аутентификаций
Сущесвтует 4 типа аутентификации:
  • BASIC – передает логин и пароль пользователя в закодированом (не зашифрованом) виде;
  • DIGEST – более защищенный, чем BASIC метод, однако контейнеры не обязаны его поддерживать;
  • CLIENT-CERT – использует Public Key Certificates (PKG);
  • FORM – позволяет вам самим создать форму для аутентификации. Логин и пароль посылаются в HTTP-запросе без кодирования.
Пример описания типа аутентификации в дескрипторе развёртывания:
Для BASIC, DIGEST и CLIENT-CERT достаточно указать так:
<login-config>
    <auth-method>BASIC</auth-method>
</login-config>
Для FORM нужно описать еще немного:
<login-config>
    <auth-method>FORM</auth-method>
    <form-login-config>
        <form-login-page>/loginPage.html</form-login-page>
        <form-error-page>/loginError.html</form-error-page>
    </form-login-config>
</login-config>
Внутри loginPage.html пишем:
<form method=”POST” action=”j_security_check”>
    <input type=”text” name=”j_username”>
    <input type=”password” name=”j_password”>
    <input type=”submit” value=”Enter”>
</form>
Защита передаваемых данных
В работе приложения обычно есть места, которые имеет смысл отсылать в сыром виде, и есть, которые следует шифровать через SSL.
Настроить степень защиты данных можно через дескриптор развёртывания, например так:
<user-data-constraint>
    <transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
Параметрами <transport-guarantee> могут быть:
  • NONE – отключает защиту данных (используется по-умолчанию);
  • INTEGRAL – что данные не должны быть изменены во время передачи;
  • CONFIDENTIAL – данные не должны быть увидены никем во время передачи;
Хотя это и не указано в спецификациях, но на практике многие контейнеры используют SSL при значениях параметра INTEGRAL и CONFIDENTIAL, так что они фактически делают одно и то же.

Комментариев нет:

Отправить комментарий

Примечание. Отправлять комментарии могут только участники этого блога.