#security #java-ee-6 #servlet-filters
#Безопасность #java-ee-6 #сервлет-фильтры
Вопрос:
Я пытаюсь реализовать функцию запоминания меня в своем приложении Java ee 6, но у меня возникают проблемы с объединением ее со встроенной функцией безопасности. У меня есть следующая конфигурация в моем web.xml:
<login-config>
<auth-method>FORM</auth-method>
<realm-name>my-realm</realm-name>
<form-login-config>
<form-login-page>/login.jsf</form-login-page>
<form-error-page>/login.jsf</form-error-page>
</form-login-config>
</login-config>
То, что я пытаюсь создать, — это фильтр, который автоматически регистрирует пользователя в том, что срок его сеанса истек, если у него есть файл cookie, содержащий некоторые данные. Это работает, но при вызове фильтра перенаправление на login.jsf уже вступило в силу, прежде чем я что-либо изменю, чтобы что-либо с этим сделать. Я предположил, что фильтры вызываются перед собственной системой безопасности java ee, поскольку они фактически вызываются на защищенных страницах, но, похоже, это не так. Есть ли какой-нибудь способ позволить пользователю перейти на ту же страницу, которую они запросили, вместо перенаправления на login.jsf?
Фильтр:
@WebFilter(
filterName="authFilter",
servletNames={
"Faces Servlet"
}
)
public class AuthFilter implements Filter {
public AuthFilter() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
User user = (User)req.getSession().getAttribute("user");
if(user == null){
String uuid = CookieUtil.getCookieValue(req, "rememberme");
if(uuid != null){
UserBean userBean = EJBUtil.lookup(UserBean.class);
RememberMe rememberme = userBean.findRememberMe(uuid);
if(rememberme != null){
user = rememberme.getUser();
try{
req.login(user.getEmail(), user.getPasswordDigest());
req.getSession().setAttribute("user", user);
CookieUtil.addCookie(res, "rememberme", uuid, CookieUtil.AGE_ONE_YEAR);
}catch(ServletException e){}
}
else{
CookieUtil.removeCookie(res, "rememberme");
}
}
}
chain.doFilter(request, response);
}
@Override
public void destroy() {
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
}
Ответ №1:
Аутентификация, управляемая контейнером, действительно вызывается перед всеми фильтрами. Это ограничение безопасности.
В основном у вас есть 3 варианта:
- Вместо этого используйте программную фильтрацию и войдите в систему, чтобы у вас был более точный контроль.
- Вместо этого выполните задание в
preRenderView
методе событий компонента, связанного сlogin.jsf
. - Возьмите фреймворк, который поддерживает функцию «Запомнить меня» поверх прозрачно управляемой безопасности контейнера, такой как Apache Shiro или Spring Security.
Комментарии:
1. 1. Похоже, что этот подход займет много времени, при этом безопасность ухудшится, и придется заново изобретать систему сопоставления URL-адресов и т.д. Просто для решения очень маленькой проблемы. 2. Как это поможет? Пользователь все равно будет перенаправлен на login.jsf, и я бы понятия не имел, откуда он взялся. 3. Я проверил Spring Security, но, похоже, у него был полностью свой собственный механизм безопасности, что означало бы необходимость в основном переделать весь мой код безопасности / конфигурацию. Даже если бы он поддерживал request.login(), мне не нужно было бы дублировать большинство моих настроек ограничений?
2. Shiro действительно выглядит интересно, если его можно легко реализовать
3. 1. Верно, вы в основном изобретаете некоторые шипы колеса. 2. Исходный URI должен быть доступен в качестве одного из атрибутов запроса (извините, не знаю ключ сверху, посмотрите на карту атрибутов запроса). 3. Я никогда не использовал Spring Security, но понимаю, что его можно использовать в сочетании с CMS (из документов SS: Хотя мы рекомендуем людям использовать Spring Security для аутентификации и не интегрировать с существующей аутентификацией, управляемой контейнером, она, тем не менее, поддерживается — как и интеграция с вашей собственной системой аутентификации. ).
4. около 2: HttpServletRequest.getRequestURI указывает на мою страницу входа в систему, а HttpServletRequest.getParameterMap пуст, поэтому я действительно не думаю, что исходный URL доступен.
5. Атрибуты запроса, а не параметры запроса.
ExternalContext#getRequestMap()
должен предоставить сопоставление их всех.