Как сохранить аутентифицированного пользователя в JASPIC?
Я разработал модуль аутентификации безопасности (SAM) и реализовал validateRequest
метод. У меня также есть простой веб-приложение, настроенное для использования этого SAM.
В моем validateRequest
метод, я проверяю clientSubject и устанавливаю CallerPrincipalCallback
с жестко заданным именем пользователя и GroupPrincipalCallback
с жестко заданным названием группы:
final CallerPrincipalCallback callerPrincipalCallback = new CallerPrincipalCallback(clientSubject, "anonymous");
final GroupPrincipalCallback groupPrincipalCallback = new GroupPrincipalCallback(clientSubject, new String[] {"user"});
try {
this.handler.handle(new Callback[] {callerPrincipalCallback, groupPrincipalCallback});
} catch (IOException | UnsupportedCallbackException e) {
logger.error(e.getMessage());
}
Я заметил, что каждый раз, когда я обновляю сервлет в своем веб-приложении, тема клиента просто пуста, logger.debug("Client: {}", clientSubject);
:
2015-05-05 11:21:02,200 DEBUG n.m.j.s.Saml2AuthModule [http-listener-1(2)] Client: Subject:
Можно ли как-то "сохранить" тему, чтобы тема была присоединена к сеансу, и я могу просто пропустить вход в систему одного и того же пользователя каждый раз?
РЕДАКТИРОВАТЬ Я думаю, что я нашел способ вручную сохранить его в HttpSession
: req.getSession().setAttribute("subject", user);
Не красиво, но это работает.
1 ответ
Можно ли как-то "сохранить" тему, чтобы тема была присоединена к сеансу, и я могу просто пропустить вход в систему одного и того же пользователя каждый раз?
Да, хотя JASPIC был спроектирован так, что он не имеет состояния, у него есть возможность полуавтоматизировать запоминание имени входа.
Эта опция, однако, на самом деле не намного меньше кода, чем просто сохранение деталей в сеансе и повторная аутентификация в начале каждого запроса.
Способ сделать это - сначала установить логическое значение в информационной карте сообщения перед возвратом SUCCESS и выходом validateRequest
:
messageInfo.getMap().put("javax.servlet.http.registerSession", TRUE.toString());
Затем в начале каждого запроса ваш модуль аутентификации (SAM) все еще вызывается, но вы можете выполнить следующий "протокол", чтобы повторно использовать сохраненные идентификационные данные (имя пользователя + роли):
HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage();
Principal userPrincipal = request.getUserPrincipal();
if (userPrincipal != null) {
handler.handle(new Callback[] {
new CallerPrincipalCallback(clientSubject, userPrincipal) }
);
return SUCCESS;
}
Я написал запись в блоге с некоторыми более подробной информацией. Вы можете найти тест, который использует полностью рабочий пример, в проекте примеров Java EE 7.
К сожалению, в JASPIC нет функциональности, позволяющей сказать, что вы вообще не хотите вызывать SAM, если сеанс (http) действителен.
Если вам нужна эта функция, проголосуйте за следующую проблему: https://java.net/jira/browse/JASPIC_SPEC-20
Я думаю, что нашел способ, сохранив его вручную в HttpSession: req.getSession(). SetAttribute("subject", user); Не красиво, но это работает.
Более или менее "официальным" способом является сохранение имени пользователя и ролей внутри сеанса, а затем в начале каждого вызова validateRequest
проверьте, есть ли эти данные, и если да, передайте их двум обратным вызовам.
Метод, который я показал выше, не очень отличается от этого, но, за исключением очевидных различий (один обратный вызов против двух, получение принципала из запроса против получения его из сеанса), основное отличие состоит в том, что через полуавтоматический способ контейнер является свободно использовать любой механизм для хранения данных.
Это может быть просто атрибут в сеансе (простая реализация JASPIC могла бы это сделать), или он мог бы использовать некоторую скрытую часть сеанса, которую имеет большинство контейнеров. Эта скрытая часть не доступна напрямую для пользовательского кода, что может иметь некоторые преимущества.