MVC拦截器vs春季安全过滤器vs其他……?
问题内容:
我将带有Spring Security的Spring-MVC用于我的Web应用程序。它包括用户注册页面和私人用户面板。我目前使用以下网址格式进行了设置:
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;
}
。
这是有效的方法吗?还有其他建议吗?
问题答案:
所有选项均有效,这取决于所需的抽象级别。
在中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
为该异常声明一个,在那里您可以完全控制响应的生成方式:(一个ModelAndView
和相关的),a
ResponseEntity
,使用注释处理程序@ResponseBody
,直接编写响应等。我觉得您拥有更多的控制权, 如果你想要的话。