Я проводил некоторое время, оценивая параметры, доступные для надежной аутентификации пользователя в приложении Java EE.
Итак, пожалуйста, предложите, чтобы варианты, перечисленные ниже, были действительны вместе с утверждениями о преимуществах или недостатках. Возможно, мне не хватает деталей, которые могли бы сделать метод аутентификации жизнеспособным. Или может быть, есть еще один вариант, который я пропустил (опять мы говорим строго java EE, поэтому нет проверки подлинности запроса и что нет, если это не может быть выполнено с помощью EE-совместимого способа)
1. Проверка подлинности DIGEST/BASIC
<security-constraint>
<web-resource-collection>
<web-resource-name>admin</web-resource-name>
<url-pattern>/protected/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>DIGEST/BASIC</auth-method>
<realm-name>as-defined-secuity-realm</realm-name>
</login-config>
<сильные > Преимущества
-
Это дружественный способ проверки подлинности REST. Вы можете отправить учетные данные авторизации с помощью вызова AJAX. После аутентификации пользователя браузер будет сопровождать любые запросы соответствующим заголовком
Authorization: Basic/Digest QWxhZGRpbjpvcGVuIHNlc2FtZQ==
. В случае неправильных учетных данных пользователю будет представлен экран уродливого браузера - если вы можете жить с этим, то для вас будет использоваться пароль BASIC/DIGEST. -
В случае Digest строка, переданная на сервер, представляет собой зашифрованную строку MD5, которая, безусловно, более безопасна, чем Basic (которая является кодировкой Base64 строки "user: password" ), но тем не менее decipherable. Таким образом, с точки зрения безопасности BASIC в значительной степени безопасен как аутентификация FORM, а DIGEST - самый безопасный из всех. В заключение, если ваш сайт полностью HTTPS (я имею в виду полностью, потому что, если некоторые ресурсы извлекаются через HTTP, ваши заголовки полномочий, например, будут видны третьей стороне), вы можете безопасно использовать BASIC/DIGEST,
- Простота настройки.
Недостатки
- Выход из системы сложный для реализации. См. здесь и здесь. Убедитесь, что у вас есть хороший запрос AJAX, который аутентифицирует пользователя, но вам также нужно иметь AJAX? запрос, который отходит от пользователя, - чтобы снова появиться окно входа в браузер). Кстати, хороший сервлет 3.0 request.logout() метод не работает должным образом в этом случае.
- Тайм-ауты сеанса очень трудно реализовать. Завершение сеанса происходит (это задача контейнера сервлета), но браузер отправляет заголовки полномочий на следующий запрос, инициируя повторную аутентификацию.
- Нет персонализированной страницы входа. Никто.
- Трудно отслеживать заверенные сеансы.
2. Аутентификация на основе FORM
<security-constraint>
<web-resource-collection>
<web-resource-name>admin</web-resource-name>
<url-pattern>/protected/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>FORM</auth-method>
<realm-name>as-defined-security-realm</realm-name>
<form-login-config>
<form-login-page>/auth/login.html</form-login-page>
<form-error-page>/auth/error.html</form-error-page>
</form-login-config>
</login-config>
Короче говоря, если пользователь обращается к URL-адресу protected/*
, страница входа в систему включена в ответ. Поэтому вместо содержимого, которое пользователь ожидает, он получит страницу входа, настроенную в теге form-login-page
. Если пароль в порядке, он будет перенаправлен (302 Paged Moved Permently) на первоначально запрошенный URL protected/*
. Если пароль NOK, пользователь будет перенаправлен (302 Paged Moved Permently) на страницу с ошибкой.
<сильные > Преимущества
- Персонализированная страница входа - эта, по-видимому, самая популярная:)
- Выйти легко. Нужно только аннулировать HttpSession или вызвать метод request.logout() (Servlet 3.0).
- Тайм-ауты сеанса
- ЕСЛИ И ТОЛЬКО Если вы принимаете отдельную страницу для входа, это решение для вас.
Недостатки
- ОТДЫХ недружественный (я не собираюсь копаться в философии отдыха, и сохранение состояния на стороне сервера не является дебатом RESTful. Мы анализируем аутентификацию REST в режиме JAVA EE, а состояние на стороне сервера всегда поддерживается для любых аутентифицированный субъект). Что действительно плохо в использовании проверки подлинности FORM - это тот факт, что в браузерах не может быть последовательного поведения. И все это связано с перенаправлением 302, которое некоторые браузеры обрабатывают в функциях ответа AJAX, а другие перенаправляют всю страницу (изменение URL-адреса в навигационной панели). Подробнее здесь и здесь. Вы не можете обойти это перенаправление 302, так что для вас не будет никакой проверки FORM и REST!!
3. Программная аутентификация
Настройте URL-адрес для проверки подлинности. За этим URL-адресом вы можете иметь сервлет, который создает экземпляр модуля входа в систему (путь JAAS) и вызывает метод HttpServletRequest.login(пользователь, пропуск) вместе с учетными данными. Он должен генерировать ответ 401/403, если логин завершился неудачно.
Вы можете реализовать его, просто указав ограничения безопасности в вашем web.xml:
<security-constraint>
<web-resource-collection>
<web-resource-name>admin</web-resource-name>
<url-pattern>/protected/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
На стороне сервера вам просто нужно настроить службу RESTFul, которая проверяет подлинность вызывающего абонента. Вот пример кода:
@Path("/auth")
@ApplicationPath("/rest")
public class AuthenticationRestFacade {
@POST
@Path("/login")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public User login(User loginInfo, @Context HttpServletRequest request) throws LoginException, ServletException {
// nasty work-around for Catalina AuthenticatorBase to be able to
// change/create the session cookie
request.getSession();
request.login(loginInfo.getName(), loginInfo.getPassword());
<сильные > Преимущества
- Персональная страница входа.
- Совместимость AJAX/REST
- URL выхода (если для этого настроен URL-адрес)
- Тайм-ауты сеанса (управление контейнером)
- В ответе вы можете вернуть данные входа (имя пользователя, адрес электронной почты, роли, группы и т.д.) (хорошо, потому что вам не нужно делать другой звонок после успешного входа в систему)
Недостатки
- Нуждается в написании кода.
- Требуется, чтобы приложение могло обрабатывать ответы 401/403 и отображать окно входа в систему.
В заключение, лучшие жизнеспособные варианты:
- Если вам не нужны таймауты сеанса или выход из системы → DIGEST
- Если приведенное выше не работает для вас. И вам не нужно иметь встроенную страницу входа (или страницу с моделями на панели), и с тобой все в порядке с одной страницей для аутентификации → FORM
- Если вышеуказанное не работает для вас, и вы хотите, чтобы вся гибкость и совместимость в мире шли с помощью подхода PROGRAMMATIC. Вы должны определить URL входа/выхода из системы, а также ваш код клиента должен иметь возможность справиться с ответами 401/403 (не просто).
Надеюсь, вы, ребята, предложите некоторые жизнеспособные альтернативные решения. Потому что сейчас я бы НЕНАВИЖУ пойти с помощью подхода ПРОГРАММЫ