在之前的博文里,我解决了前端和后台的通讯问题,也解决了Ajax取得验证结果后直接跳转到主页面的问题,在实际的使用后,我又发现了一个问题:登录后可以跳转至主页面,这很合理,但没有登录的人也可以访问主页面,这就有点尴尬了。
所以现在的问题是,如何才能阻止那些没有登录的人访问主页面呢?
开门的钥匙
经过一段时间的学习,我发现了一种被称为session的东西。它由服务器生成,由服务器保存,可以用来识别出那些已经登录的人。举个例子,用户A登录后,服务器给他生成一条他自己独有的session,他每次尝试访问主页时,服务器都会检查他之前是否获得过session,如果没有session,说明他是没有登录过的人,必须将他重定向到登录页面。
所以,session是一种开门的钥匙,拥有session的人才有资格访问主页面。
SpringMVC的审核门
既然我们使用session机制可以识别已经登录的人,那么SpringMVC中有没有什么关卡,可以将那些没有钥匙的人挡在外面?
答案是:有,拦截器!拦截器可以审核URL请求,合法的就放行让服务器进行响应,不合法的就拦下来。
session的使用
在接受登录请求的控制器里,当用户的密码正确时,在代码里加入两行:
1 2
| httpSession.setAttribute(StudentConst.STUDENT_EMAIL, email); httpServletResponse.addCookie(new Cookie(StudentConst.STUDENT_EMAIL, email));
|
它会在服务器中为该用户生成一条键为StudentConst.STUDENT_EMAIL(该常量代码的字符串是“EMAIL”)值为email变量所指向字符串的session,同时也命令浏览器生成相应的cookie来保存session。
如此一来,登录过的用户就拥有session记录了,没登录的自然没有。
在拦截器里,我们将“是否拥有session”作为审核通过的唯一因素,就能将未登录的人挡在门外咯。
拦截器的使用
首先我们在Spring的WEB层配置文件(spring-web.xml)中声明一个拦截器的拦截范围:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/student/**"/> <mvc:exclude-mapping path="/student/register"/> <mvc:exclude-mapping path="/student/login"/> <mvc:exclude-mapping path="/student/common/**"/> <mvc:exclude-mapping path="/student/css/**"/> <mvc:exclude-mapping path="/student/js/**"/> <bean class="com.ilovecl.interceptor.StudentSessionInterceptor"/> </mvc:interceptor>
|
当用户请求localhost:8080/student/dashboard时就将该请求转交给StudentSessionInterceptor进行处理,该拦截器的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| package com.ilovecl.interceptor;
import com.ilovecl._const.StudentConst; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
public class StudentSessionInterceptor implements HandlerInterceptor { private Logger logger = LoggerFactory.getLogger(this.getClass());
@Override public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception { Object email = httpServletRequest.getSession().getAttribute(StudentConst.STUDENT_EMAIL); if (email == null) { logger.info("用户尚未登录,将其重定向至登录页面"); httpServletResponse.sendRedirect("/student/login"); return false; } return true; }
@Override public void postHandle(HttpServletRequest hsr, HttpServletResponse hsr1, Object o, ModelAndView mav) throws Exception { }
@Override public void afterCompletion(HttpServletRequest hsr, HttpServletResponse hsr1, Object o, Exception excptn) throws Exception { }
}
|
拦截器里有个名为preHandle
的方法,它在服务器处理URL请求之前,先审核URL请求,以便决定是否进行拦截。如果该用户没有session,那就将其重定向httpServletResponse.sendRedirect("/student/login");
,并返回false表示不放行,否则返回true表示放行。