В настоящее время мы пытаемся реализовать веб-приложение, использующее механизм аутентификации Java EE с логином на основе FORM, внутри веб-контейнера Websphere 6.1. Если аутентификация прошла успешно, у нас все работает; извлекаются группы членства LDAP, выполняется сопоставление групп с ролями, а роли возвращаются и правильно интерпретируются веб-приложением.
Если аутентификация не удалась, возвращается страница с ошибкой входа в систему. Однако это статическая страница, на которой просто написано что-то вроде «произошла ошибка». Как нам отловить конкретную ошибку, которая помешала успешному входу в систему (неверное имя пользователя / пароль, недоступен репозиторий LDAP, учетная запись заблокирована, срок действия пароля истек и т. д.)? Похоже, что должен быть какой-то простой способ сделать это, так как вы хотели бы обрабатывать некоторые исключения «безопасности» иначе, чем другие.




Это древнее знание - я считаю, что сделал такое с котом. Насколько я помню, не существовало стандартного способа, поскольку реализация была полностью отделена от запросов и веб-материалов внешнего интерфейса, поэтому было трудно установить какие-либо средства связи между компонентом аутентификации и внешним интерфейсом (например, страница ошибки ).
В итоге мы выбрали способ, специфичный для tomcat, в значительной степени полагаясь на текущую реализацию. Я больше не работаю в этой компании, поэтому не могу сказать о текущем состоянии кода или решении, которое мы выбрали тогда. Я считаю, что вам также понадобится какое-то конкретное решение Websphere - будь то использование локальных переменных потока, ввод сообщений с именем пользователя, который пытался войти в систему, каким-то образом получение идентификатора сеанса или что-то подобное.
Проверьте эту статью Защита приложений J2EE с помощью фильтра сервлетов. Я считаю, что это покрывает ваше требование, чтобы указать причину ошибки аутентификации.
Я использую Struts, поэтому он будет выполнять пересылку за вас. Если у вас нет фреймворка (почему бы и нет?), Вам придется делать это вручную.
Спецификация Java EE охватывает сервлет j_security_check.
Страница входа отправляет сообщения j_username и j_password сервлету j_security_check. Ваше приложение будет настроено на ошибку для неавторизованной страницы (см. Web.xml), но (изначально) будет вызывать сервлет. 401 или 403 перейдут на запрещенную страницу (снова web.xml)
Внутри этого сервлета (который расширяет HttpServlet) вы проверите все эти хорошие вещи.
public final void doGet(javax.servlet.http.HttpServletRequest request,
javax.servlet.http.HttpServletResponse response)
throws javax.servlet.ServletException, java.io.IOException
{
// initialize the app
AppInit initializer = new AppInit();
// get the logger
log = new Log4jWrapper(this.getClass());
// initialize the application session
HttpSession sess = request.getSession(true);
sess.setAttribute(CommonConstants.SESSION_CURR_USER_ID, request.getRemoteUser());
// initialize the JSP to forward to based on the user role
String fwdJSP = "SetupMainPage.jsp";
if (request.isUserInRole(CommonConstants.ROLE_MANAGER)) {
log.debug("User is a Manager");
}
//else other role checks - (these are users in groups in the LDAP)
// initialize the application session and set a variable to indicate that
// we are coming from a first time login (not a timeout login)
sess.setAttribute(CommonConstants.SESSION_COMING_FROM_INITIAL_LOGIN,"TRUE");
disp = getServletContext().getRequestDispatcher("SetupMainPage.jsp");
disp.forward(request, response);
}
//else failure
Неизвестный пользователь
[11/22/08 8:54:47:993 EST] 7f6ac69c FormLoginServ E SECJ0118E: Authentication error during authentication for user s
правильный пользователь - неправильный пароль, но request.getRemoteUser () будет иметь значение
[11/22/08 8:56:45:082 EST] 7f51469c FormLoginServ E SECJ0118E: Authentication error during authentication for user jbsymolo
К сожалению, у меня нет примеров того, что кто-то заблокирован, но я предполагаю, что в главном каталоге безопасности (LDAP) у вас будет запись для пользователя для этого.
Это от кого-то другого (поэтому я не могу поверить в это)
I think this page describes how to do what you want to do.
Specifically how to retrieve the authentication exception from an arbitrary underlying authentication source (looks like Websphere calls them user registries).
Throwable t = com.ibm.websphere.security.auth.WSSubject.getRootLoginException();
if (t != null)
t = determineCause(t);Where determineCause() is defined on the same page. This way, even if your server is configured to authenticate against a John Deer tractor, you will have access to the "OutOfGasLoginException" if there is one. The above code can go into the Servlet, Servlet Filter, or JSP that is redirect to by the container (as described above by jsymolon). It simply examines the exceptions and then places a corresponding friendly error message on the resulting page.
Интересно - я никогда не пробовал реализовать свой собственный сервлет j_security_check. Я всегда предполагал, что контейнер позаботится об этом, и приложение не сможет увидеть пароль. Проверю сразу ...
Извините - это вводит в заблуждение. Вам не нужно реализовывать свой собственный сервлет j_security_check, поскольку этим занимается Websphere. Используйте приведенный выше код, чтобы проверить, что выходит из этого сервлета, и предпринять действия.
Спецификация JavaEE не предоставляет стандартного средства для получения обратной связи об аутентификации, например кодов ошибок.
Согласно следующему IBM Redpaper об интеграции безопасности z / OS в сером примечании на стр. 57: Доступно специальное расширение IBM, чтобы страница ошибки JSP могла сообщать о конкретном сообщении (например, истек срок действия пароля) на основе кода состояния ошибки.
Согласно WebSphere InfoCenter образец FormLoginWeb из пакета TechSamp в вашей установке WebSphere (samples/src/TechSamp/FormLoginWeb) должен демонстрировать такое специфическое расширение IBM, но ... Единственное, что интересно, - это LoginFilter, который перехватывает вызовы на /j_security_check и может выполнять предварительный вход в систему проверка и действия после входа в систему, как описано в подробности в этой статье.
С помощью такого механизма можно получить исключение входа из JAAS Subject и установить код ошибки входа в HttpSession, чтобы страница ошибки могла генерировать конкретное сообщение.
Этот API предоставляет способ подключить ваш собственный конкретный механизм аутентификации в контейнер JavaEE. Если вы хотите получить обратную связь от реализации аутентификации LDAP, предоставленной поставщиком, вам нужно будет создать оболочку вокруг нее, чтобы предоставить доступ к деталям сбоя аутентификации из вашего прикладного кода. Нет, не существует спецификации JavaEE для приложения, которое могло бы получать сведения об ошибке аутентификации из серверной части.
Что ж, если используется профиль моста LoginModule, исключение LoginException, которое он генерирует, должен выбрасывает соответствующий AuthException. Достаточно ли этого AuthException стандартизированной обратной связи - это, конечно, открытый вопрос.
ОК для базовой реализации. Теперь, как код приложения Servlet / JSP может получить исключение LoginException или AuthException, чтобы сообщить о соответствующей обратной связи пользователя на экране входа в систему?
Не знаю, думаю, это зависит от приложения. Может, несколько сотен тысяч? Или это слишком? Вы знаете сколько? Если я вхожу в веб-приложение (java) и ввожу неправильные учетные данные, это обычно дает мне какую-то обратную связь. Но, может быть, вы не это имеете в виду?
Хорошая статья, но я прочитал вопрос «как мне сообщить об ошибках во время аутентификации пользователю». Аутентификация (в JEE) отделена от приложения, поэтому фильтры не могут перехватить запрос (и имя пользователя / пароль), используемый для входа в систему. Обычно это хорошо, за исключением таких ситуаций ...