Подтвердить что ты не робот

MVC перехватчик vs Spring фильтр защиты против чего-то еще...?

Я использую Spring -MVC с Spring Безопасность для моего веб-приложения. Он включает страницы регистрации пользователей и частную панель пользователя. В настоящее время он настроен со следующими шаблонами URL:

  • whatever/myapp/login войти в систему
  • whatever/myapp/register?step=1 начать регистрацию
  • whatever/myapp/account/** виды частной области (страницы)
  • whatever/myapp/pending просмотр показан во время процессов после регистрации
  • whatever/myapp/blocked заблокированный аккаунт
  • whatever/myapp/register/retry, если регистрация не удалась, разрешить повтор

По существу, для этих URL-адресов требуется аутентификация пользователя, т.е. требуется вход в систему:

  • whatever/myapp/account/** (страницы частной области)
  • whatever/myapp/pending (на этой странице установлен таймер для перенаправления на /account/home )
  • whatever/myapp/register/retry

Для обеспечения безопасности Spring это довольно просто. Однако независимо от аутентификации пользователя через Spring безопасность, страницы частной области должны быть доступны или нет, в зависимости от текущего состояния учетной записи пользователя (хранящегося в моей БД).

В частности: если пользователь пытается получить доступ к чему-либо в частной области (/account/**), ему должно быть показано соответствующее представление (перенаправлено на соответствующую страницу) в соответствии с состоянием. У меня эти статусы определены:

  • suspended - относится к ожидающему виду
  • enabled - разрешить полный доступ
  • disabled - здесь не актуально
  • retry_allowed - относится к представлению повтора
  • blocked - относится к просмотру с заблокированным счетом

В настоящее время у меня установлена ​​перехватчик MVC на /account/**, которая проверяет статус пользователя и перенаправляет на соответствующие страницы, но почему-то я понимаю, что это не идеальное или подходящее решение здесь, так как я сталкиваюсь странное поведение, например, вызов нескольких контроллеров... и также я не совсем уверен, когда возвращать true/false в рамках метода preHandle(). Здесь фрагмент кода от перехватчика:

@Override
public boolean preHandle(
    HttpServletRequest request, 
    HttpServletResponse response,
    Object arg2) 
    throws Exception {

IPanelUser pUser =  (IPanelUser) SecurityContextHolder.getContext()
        .getAuthentication().getPrincipal();

// check principal first and then load from DB
// "suspended" is initial status upon registration
if(pUser.getCustomer().getStatus() == CustomerStatus.Suspended.getCode()) {

    // if suspended, load from DB and update status
    Customer customer = this.customerService.getUserByUsername(pUser.getUsername());
    if(customer != null)
        pUser.getCustomer().setStatus(customer.getStatus());

    // still suspended? redirect to pending
    if(pUser.getCustomer().getStatus() == CustomerStatus.Suspended.getCode()) {
        response.sendRedirect("../pending");
        return false;
    }
}

if(pUser.getCustomer().getStatus() == CustomerStatus.Blocked.getCode()) {

    // redirect to blocked page
    response.sendRedirect("../blocked");
    SecurityContextHolder.clearContext();
    return false;
}

if(pUser.getCustomer().getStatus() == CustomerStatus.AllowRetry.getCode()) {

    // redirect to CC submission page
    response.sendRedirect("../register/retry");
    return false;
}

if(pUser.getCustomer().getStatus() == CustomerStatus.Enabled.getCode() ||
   pUser.getCustomer().getStatus() == CustomerStatus.Disabled.getCode()) {

    // do nothing
}

return true;
}

.

Это действительный подход? Любые альтернативные предложения?

4b9b3361

Ответ 1

Все параметры действительны, это зависит от уровня абстракции, который вы хотите.

В Filter у вас есть доступ только к объектам HttpServletRequest и HttpServletResponse, поэтому вы очень тесно связаны с API Servlet. У вас также нет (напрямую) доступа ко всем замечательным функциям Spring, таким как возврат отображаемого представления или ResponseEntity.

В a HandlerInterceptor он снова больше того же. Вы можете выполнить перенаправление или запрос непосредственно в preHandle(), где у вас нет доступа к ModelAndView, или установить флаг, который вы проверяете postHandle(). У вас будет доступ к ModelAndView, но не к некоторым другим функциям Spring MVC.

Spring Безопасность - хорошая альтернатива, но я нахожу, что у нее много настроек, которые мне не нравятся.

Одна из последних альтернатив, которые мне больше всего нравятся, - использовать AOP (вы можете сделать это с помощью Spring Security или Shiro). Вы создаете аннотацию типа @Private, и вы комментируете свои методы обработчика @Controller. Вы используете AOP, чтобы сообщить об этих методах. В основном совет проверяет некоторый атрибут сеанса или запроса для флага (разрешен или нет). Если вам разрешено, вы продолжаете выполнять метод обработчика, если нет, вы бросаете UnauthorizedException (или аналогичный). Затем вы также объявляете @ExceptionHandler для этого исключения, где у вас есть довольно полный контроль над тем, как генерируется ответ: a ModelAndView (и связанный), a ResponseEntity, аннотировать обработчик с помощью @ResponseBody, написать ответ напрямую и т.д. Я чувствую, что у вас есть намного больше контроля, если вы этого хотите.