繁体   English   中英

MVC拦截器与Spring安全过滤器vs其他东西......?

[英]MVC interceptor vs Spring security filter vs something else…?

我在我的Web应用程序中使用Spring-MVC和Spring Security。 它包括用户注册页面和私人用户面板。 我现在设置了以下网址模式:

  • 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/** ,它检查用户状态,并重定向到适当的页面,但不知何故,我觉得这不是真正理想或适当的解决方案,因为我面临奇怪行为,就像多个控制器调用一样...而且我不太确定何时在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 ,您只能访问HttpServletRequestHttpServletResponse对象,因此您非常适合使用Servlet API。 您也没有(直接)访问所有伟大的Spring功能,例如返回要呈现的视图或ResponseEntity

HandlerInterceptor ,它再次变得更加相同。 您可以直接在preHandle()中进行重定向或请求处理,在preHandle()中您无权访问ModelAndView或设置您在postHandle()检查的标志。 您可以访问ModelAndView但不能访问其他一些Spring MVC功能。

Spring Security是一个不错的选择,但我发现它有很多我不太喜欢的配置。

我最喜欢的最后一个选择是使用AOP(你也可以使用Spring Security或Shiro)。 您可以创建类似@Private的注释,并注释@Controller处理程序方法。 您使用AOP建议这些方法。 该建议基本上检查一些会话或请求属性的标志(授权与否)。 如果允许,则继续执行处理程序方法,否则,抛出UnauthorizedException (或类似)。 然后,您还可以为该异常声明一个@ExceptionHandler ,您可以完全控制响应的生成方式: ModelAndView (及相关), ResponseEntity ,使用@ResponseBody注释处理程序,直接编写响应等等。我觉得就像你有更多的控制权,如果你想要的话。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM