2013-10-10 2 views
13

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

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

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

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

Это довольно просто ас hieve, используя Spring security. Тем не менее, независимо от аутентификации пользователя с помощью функции 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; 
} 

.

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

ответ

21

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

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

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

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

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

Смежные вопросы