Spring3 MVC Login Interceptor(Spring 拦截器)
------------------------------------------------------------------------------------------------------------------------------------------------------------------
原文: http://my.oschina.net/uniquejava/blog/83657
在学spring3 mvc,做了个简单的CRUD,但是用户不登录也能直接访问任何页面。我的想法是写个SecurityInterceptor在preHandle中判断session是不是存在user对象。配置如下:
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/*" />
<bean class="smartcrud.common.spring.SecurityInterceptor">
</bean>
</mvc:interceptor></mvc:interceptors>
代码如下:
public class SecurityInterceptor implements HandlerInterceptor {
@Override public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception { // intercept
HttpSession session = request.getSession(); if (session.getAttribute("user") == null) { throw new AuthorizationException();
} else { return true;
}
}
很快,我发现登录页面是不需要拦截的。。搜索了一下。<mvc:interceptor>没有提供配置exclude url的功能。只能在SecurityInterceptor中手动处理。。于是修改配置如下:
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/*" />
<bean class="smartcrud.common.spring.SecurityInterceptor">
<property name="excludedUrls">
<list>
<value>/login</value>
</list>
</property>
</bean>
</mvc:interceptor></mvc:interceptors>
修改代码如下:
public class SecurityInterceptor implements HandlerInterceptor { private List<String> excludedUrls; public void setExcludedUrls(List<String> excludedUrls) { this.excludedUrls = excludedUrls;
}
@Override public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception { // excluded URLs: // see http://stackoverflow.com/questions/9908124/spring-mvc-3-interceptor-on-all-excluding-some-defined-paths
String requestUri = request.getRequestURI(); for (String url : excludedUrls) { if (requestUri.endsWith(url)) { return true;
}
} // intercept
HttpSession session = request.getSession(); if (session.getAttribute("user") == null) { // see http://stackoverflow.com/questions/12713873/spring-3-1-how-do-you-send-all-exception-to-one-page
throw new AuthorizationException();
} else { return true;
}
}
这样以/login结尾的请求不做拦截处理。。
接下来需要处理非/login结尾的情况,此时我设计为抛出一个自定义的AuthorizationException异常。
public class AuthorizationException extends Exception {
}
当抛出这个异常时,spring框架应该能够处理它,并将用户导向/WEB-INF/views/adminLogin.jsp页面以便让用户登录。。
搜索了一下资料,配置如下:
<bean id="handlerExceptionResolver"
class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="smartcrud.common.exception.AuthorizationException">redirect:/login</prop>
</props>
</property></bean>
注意这里的视图名为redirect:/login,spring会去找标记了@RequestMapping(value="/login")的方法来处理它。
代码如下:
@Controllerpublic class LoginController {
@Autowired private UserService userService;
@RequestMapping(value = "/login", method = RequestMethod.GET) public String loginForm() { return "adminLogin";
}
如果handlerExceptionResolver那里的视图名没有redirect前缀,像这样
class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings">
<props>
<prop key="smartcrud.common.exception.AuthorizationException">/login</prop>
</props>
</property></bean>
spring会尝试去找/WEB-INF/views/login.jsp。。如果恰好登录页面不叫这个名字,spring就会给出404,搞不懂spring为什么不去@RequestMapping中查找呢。