Springmvc中的拦截器是用来拦截用户请求,并进行相应处理的。比如通过拦截器来进行用户权限验证,或者用来判断用户是否已经登录等。本文是一个转载文,原文地址:https://www.cnblogs.com/Dreamer-1/p/9034800.html
在原文的末尾有源码,可下载
之前在做项目时需要实现一个简单的登录认证的功能,就寻思着使用Spring Boot的拦截器来实现,在此记录一下我的整个实现过程,源码见文章底部。
IntelliJ IDEA + Java8 + Spring Boot + Tomcat
我将之前项目中的登录模块抽离出来,单独放在了一个新建的Spring Boot项目中,整个项目的主要结构如下:
参考资料:使用IDEA创建Spring Boot项目
之前项目里别的小伙伴已经写好了一个简单的登录框样式表(login.css)和一些image图,我这里就顺手拿来用了,希望哪天你见了眼熟别拍我…
2.1.1 login.vm代码:
注意前端传递给后端Controller的password值并不是用户实际输入的密码!
实际传递的是用户名 + 密码(统一小写)组合的字符串的md5信息值;
这样在前后台数据传递及后台数据保存时传递和保存的都不是用户的真实密码值,可以一定程度提升安全性及规避某些风险;
系统登录
2.1.2 welcome.vm代码
登录成功后显示welcome.vm页的内容,这个页面很简单:
登录成功!!!
退出登录
后端代码相较于前端要复杂一些,让我们来一一拆解;
2.2.1 程序入口
ManApplication.java是整个程序的主入口,因为其上打了@SpringBootApplication的注解;
注意:Spring Boot项目在tomcat上部署运行时,ManApplication需要继承SpringBootServletInitializer类
ManApplication.java代码:
/**
* @SpringBootApplication 注解标明该类是本程序的入口
*/
@SpringBootApplication
public class ManApplication extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(ManApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(ManApplication.class, args);
}
}
2.2.2 Controller
IndexViewController.java类里就是简单的URL映射;
@Controller
public class IndexViewController {
/**
* 登录
* @return
*/
@GetMapping("/")
public String index() {
return "login";
}
/**
* 欢迎页
* @return
*/
@GetMapping("/welcome")
public String welcome() {
return "welcome";
}
}
LoginViewController.java类接收前端传过来的username和password,进行简单的校验和重定向;
此处为了简单就只设置了一个正确的账号和密码用于校验,你后续使用时可以结合自己的实际需求来扩充整个校验逻辑(比如通过专门的表来存储用户登录信息等);
用户名和密码校验通过后会在当前会话的session中放入一个登录标识,以表示当前用户已经登录;在退出登录或会话超时时销毁该标识;
@Controller
public class LoginViewController {
// 预先设置好的正确的用户名和密码,用于登录验证
private String rightUserName = "admin";
private String rightPassword = "admin";
/**
* 登录校验
*
* @param request
* @return
*/
@RequestMapping("/login")
public String login(HttpServletRequest request) {
String username = request.getParameter("username");
String password = request.getParameter("password");
if (null == username || null == password) {
return "redirect:/";
}
// 前端传回的密码实际为用户输入的:用户名(小写)+ 密码(小写)组合的字符串生成的md5值
// 此处先通过后台保存的正确的用户名和密码计算出正确的md5值,然后和前端传回来的作比较
String md5info = rightUserName.toLowerCase() + rightPassword.toLowerCase();
String realPassword = DigestUtils.md5DigestAsHex(md5info.getBytes());
if (!password.equals(realPassword)) {
return "redirect:/";
}
// 校验通过时,在session里放入一个标识
// 后续通过session里是否存在该标识来判断用户是否登录
request.getSession().setAttribute("loginName", "admin");
return "redirect:/welcome";
}
/**
* 注销登录
*
* @param request
* @return
*/
@RequestMapping("/loginout")
public String loginOut(HttpServletRequest request) {
request.getSession().invalidate();
return "redirect:/";
}
}
2.2.3 Interceptor
LoginInterceptor.java是整个登录认证模块中的核心类之一,它实现了HandlerInterceptor类,由它来拦截并过滤到来的每一个请求;它的三个方法能分别作用于每个请求的不同生命周期,你可以根据自己的需要来加入相应的处理逻辑。
public class LoginInterceptor implements HandlerInterceptor {
/**
* 在请求被处理之前调用
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 检查每个到来的请求对应的session域中是否有登录标识
Object loginName = request.getSession().getAttribute("loginName");
if (null == loginName || !(loginName instanceof String)) {
// 未登录,重定向到登录页
response.sendRedirect("/");
return false;
}
String userName = (String) loginName;
System.out.println("当前用户已登录,登录的用户名为: " + userName);
return true;
}
/**
* 在请求被处理后,视图渲染之前调用
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
/**
* 在整个请求结束后调用
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
2.2.4 Configuration
LoginConfiguration.java是另一个核心类之一,它实现了WebMvcConfigurer类,负责注册并生效我们自己定义的拦截器配置;在这里要注意定义好拦截路径和排除拦截的路径。
@Configuration
public class LoginConfiguration implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注册拦截器
LoginInterceptor loginInterceptor = new LoginInterceptor();
InterceptorRegistration loginRegistry = registry.addInterceptor(loginInterceptor);
// 拦截路径
loginRegistry.addPathPatterns("/**");
// 排除路径
loginRegistry.excludePathPatterns("/");
loginRegistry.excludePathPatterns("/login");
loginRegistry.excludePathPatterns("/loginout");
// 排除资源请求
loginRegistry.excludePathPatterns("/css/login/*.css");
loginRegistry.excludePathPatterns("/js/login/**/*.js");
loginRegistry.excludePathPatterns("/image/login/*.png");
}
}