MVC拦截器与Spring安全filtervs其他东西……?
我在我的Web应用程序中使用Spring-MVC和Spring Security。 它包括用户注册页面和私人用户面板。 我现在设置了以下url模式:
-
whatever/myapp/login
用户登录 -
whatever/myapp/register?step=1
开始注册 -
whatever/myapp/account/**
私人区域视图(页面) - 在注册后流程完成时显示的
whatever/myapp/pending
视图 -
whatever/myapp/blocked
帐户被阻止的视图 - 如果注册失败,
whatever/myapp/register/retry
,都允许重试
基本上,下面的这些URL应该要求用户身份validation,即需要登录:
-
whatever/myapp/account/**
(私人区域页面) -
whatever/myapp/pending
(此页面有一个定时器设置为重定向到/ account / home) -
whatever/myapp/register/retry
使用Spring安全性非常简单。 但是,无论通过Spring安全性进行用户身份validation,私有区域页面都应该是可访问的,具体取决于用户的当前帐户状态(存储在我的数据库中)。
更具体地说:如果用户试图访问私有区域( /account/**
)中的任何内容,则应根据状态向他显示相应的视图(重定向到适当的页面)。 我定义了这些状态:
-
suspended
– 与待审视图有关 -
enabled
– 允许完全访问权限 -
disabled
– 这里不相关 -
retry_allowed
– 与重试视图有关 -
blocked
– 与帐户被阻止的视图有关
目前,我有一个MVC拦截器设置到/account/**
,它检查用户状态,并重定向到适当的页面,但不知怎的,我觉得这不是真正理想或适当的解决方案,因为我面临奇怪行为,就像多个控制器调用一样…而且我不太确定何时在preHandle()
方法中返回true
/ false
。 这是拦截器的代码片段:
@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; }
。
这是一种有效的方法吗? 还有其他建议吗?
所有选项都是有效的,这取决于您想要的抽象级别。
在Filter
,您只能访问HttpServletRequest
和HttpServletResponse
对象,因此您非常熟悉Servlet
API。 您也没有(直接)访问所有伟大的Springfunction,例如返回要呈现的视图或ResponseEntity
。
在HandlerInterceptor
,它再次变得更加相同。 您可以直接在preHandle()
中进行重定向或请求处理,在那里您无权访问ModelAndView
或设置您在postHandle()
检查的标志。 您可以访问ModelAndView
但不能访问其他一些Spring MVCfunction。
Spring Security是一个不错的选择,但我发现它有很多我不太喜欢的配置。
我最喜欢的最后一个选择是使用AOP(你也可以使用Spring Security或Shiro)。 您可以创建类似@Private
的注释,并注释@Controller
处理程序方法。 您使用AOP建议这些方法。 该建议基本上检查一些会话或请求属性的标志(授权与否)。 如果允许,则继续执行处理程序方法,否则,抛出UnauthorizedException
(或类似)。 然后,您还可以为该exception声明一个@ExceptionHandler
,您可以完全控制响应的生成方式: ModelAndView
(和相关), ResponseEntity
,使用@ResponseBody
注释处理程序,直接编写响应等等。我觉得就像你有更多的控制权,如果你想要的话。