Java结合SpringBoot拦截器实现简单的登录认证模块
Java结合SpringBoot拦截器实现简单的登录认证模块
之前在做项目时需要实现一个简单的登录认证的功能,就寻思着使用Spring Boot的拦截器来实现,在此记录一下我的整个实现过程,源码见文章底部。
1. 环境搭建
IntelliJ IDEA + Java8 + Spring Boot + Tomcat
我将之前项目中的登录模块抽离出来,单独放在了一个新建的Spring Boot项目中;
整个项目的主要结构如下:

2. 代码详解
2.1 前端代码
之前项目里别的小伙伴已经写好了一个简单的登录框样式表(login.css)和一些image图,我这里就顺手拿来用了,希望哪天你见了眼熟别拍我…
login.vm代码:
注意前端传递给后端Controller的password值并不是用户实际输入的密码!
实际传递的是用户名 + 密码(统一小写)组合的字符串的md5信息值;
这样在前后台数据传递及后台数据保存时传递和保存的都不是用户的真实密码值,可以一定程度提升安全性及规避某些风险;
更多资料可参考:Web前端密码加密是否有意义
<html>
<head>
<title>系统登录</title>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="author" content="Dreamer-1">
<meta name="renderer" content="webkit" />
<link href="/css/login/login.css" rel="stylesheet">
<script type="text/javascript" src="/js/login/jquery/jquery.min.js?v=20170207"></script>
<script type="text/javascript" src="/js/login/md5/md5.js"></script>
</head>
<body>
<form name="form1" method="post" action="/login" id="form1" onsubmit="return checkLogin();">
<div id="main">
<div class="wrapper">
<div class="login-hd"></div>
<div class="login-body">
<div class="logo">
<span class="icon-logo"></span>
</div>
<div class="box">
<div class="login-item">
<span class="icon-user"></span>
<input name="username" type="text" id="username" class="login-input" tabindex="1" maxlength="50" placeholder="请输入用户名" />
</div>
<div class="login-item mt35">
<span class="icon-pwd"></span>
<input type="password" id="password" class="login-input" tabindex="2" maxlength="32" placeholder="请输入密码"/>
<input type="hidden" id="hidePwd" name="password">
</div>
<div class="login-forget" style="visibility:hidden">
<a href="#">忘记密码</a>
</div>
<input type="submit" name="Logon" value="登录" id="Logon" tabindex="3" class="login-btn" />
<div class="login-bottom">
<div class="msg" style="display:none;" >
<span class="icon-err"></span>
<span id="message"></span>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
<script type="text/javascript">
// onsubmit值为true时,提交表单,否则显示错误信息
// 生成用户名+密码组合的md5值,并设置传给后端的密码为该md5值
function checkLogin() {
var name = $("#username").val().toLowerCase();
var pwd = $("#password").val().toLowerCase();
if(name.trim()=="" || pwd.trim()=="") {
$("#message").text("请输入用户名和密码");
$('.msg').show();
return false;
}else {
$('.msg').hide();
}
var md5info = name + pwd;
$('#hidePwd').val(md5(md5info));
//$("#password").val();
return true;
}
</script>
</body>
</html>
welcome.vm代码
登录成功后显示welcome.vm页的内容,这个页面很简单:
<h1 align="center">登录成功!!!</h1>
<br>
<h3><a href="/loginout"><font color="red">退出登录</font></a></h3>
2.2 后端代码
后端代码相较于前端要复杂一些,让我们来一一拆解;
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映射;
/**
* Created with logindemo.
* Author: dreamer-1
* Email: zhong--lei@outllok.com
* Date: 2018/5/13
* Time: 下午2:58
* Description:
*/
@Controller
public class IndexViewController {
/**
* 登录
* @return
*/
@GetMapping("/")
public String index() {
return "login";
}
/**
* 欢迎页
* @return
*/
@GetMapping("/welcome")
public String welcome() {
return "welcome";
}
}
LoginViewController.java类接收前端传过来的username和password,进行简单的校验和重定向;
此处为了简单就只设置了一个正确的账号和密码用于校验,你后续使用时可以结合自己的实际需求来扩充整个校验逻辑(比如通过专门的表来存储用户登录信息等);
用户名和密码校验通过后会在当前会话的session中放入一个登录标识,以表示当前用户已经登录;在退出登录或会话超时时销毁该标识;
/**
* Created with logindemo.
* Author: dreamer-1
* Email: zhong--lei@outllok.com
* Date: 2018/5/13
* Time: 下午2:49
* Description:
*/
@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类,由它来拦截并过滤到来的每一个请求;它的三个方法能分别作用于每个请求的不同生命周期,你可以根据自己的需要来加入相应的处理逻辑;
/**
* Created with logindemo.
* Author: dreamer-1
* Email: zhong--lei@outllok.com
* Date: 2018/5/13
* Time: 下午2:58
* Description:
*/
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类,负责注册并生效我们自己定义的拦截器配置;
在这里要注意定义好拦截路径和排除拦截的路径;
WebMvcConfigurerAdapter其实还可以做很多其他的事,包括添加自定义的视图控制器等等,详见这里
/**
* Created with logindemo.
* Author: dreamer-1
* Email: zhong--lei@outllok.com
* Date: 2018/5/13
* Time: 下午2:58
* Description:
*/
@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");
}
}
3. 踩坑与填坑
3.1 多次重定向与Circle view path错误
刚开始程序部署至tomcat里运行时,理所当然的出现了意想不到的情况,详情如下:
启动时localhost:8080显示:

后台一直报错:

通过断点调试,发现启动后不停地进入IndexViewController中的“/”这个URL映射里;
手动指定访问路径为 localhost:8080/welcome 时后台报错:

解决办法:
- 在pom文件中导入thymeleaf依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
- 在application.properties里添加如下配置:
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.vm
我猜想可能是我的view文件都以.vm结尾,thymeleaf默认找的是.html结尾的视图,所以一直找不到;
有知道的大神可以在下面留言详细讲解一下 _
4. 大功告成
4.1 运行截图
未登录情况下访问 localhost:8080/welcome 等非登录页面时会自动跳转到登录页面:

4.2 源码下载
Java结合SpringBoot拦截器实现简单的登录认证模块的更多相关文章
- SpringBoot 拦截器--只允许进入登录注册页面,没登录不允许查看其它页面
SpringBoot注册登录(一):User表的设计点击打开链接 SpringBoot注册登录(二):注册---验证码kaptcha的实现点击打开链接 SpringBoot注册登录(三):注册--验证 ...
- 【SpringBoot】SpringBoot拦截器实战和 Servlet3.0自定义Filter、Listener
=================6.SpringBoot拦截器实战和 Servlet3.0自定义Filter.Listener ============ 1.深入SpringBoot2.x过滤器Fi ...
- SpringBoot图文教程7—SpringBoot拦截器的使用姿势这都有
有天上飞的概念,就要有落地的实现 概念十遍不如代码一遍,朋友,希望你把文中所有的代码案例都敲一遍 先赞后看,养成习惯 SpringBoot 图文教程系列文章目录 SpringBoot图文教程1「概念+ ...
- SpringBoot拦截器中Bean无法注入(转)
问题 这两天遇到SpringBoot拦截器中Bean无法注入问题.下面介绍我的思考过程和解决过程: 1.由于其他bean在service,controller层注入一点问题也没有,开始根本没意识到Be ...
- SpringBoot拦截器中service或者redis注入为空的问题
原文:https://my.oschina.net/u/1790105/blog/1490098 这两天遇到SpringBoot拦截器中Bean无法注入问题.下面介绍我的思考过程和解决过程: 1.由于 ...
- springboot + 拦截器 + 注解 实现自定义权限验证
springboot + 拦截器 + 注解 实现自定义权限验证最近用到一种前端模板技术:jtwig,在权限控制上没有用springSecurity.因此用拦截器和注解结合实现了权限控制. 1.1 定义 ...
- Java三大器之拦截器(Interceptor)的实现原理及代码示例
1,拦截器的概念 java里的拦截器是动态拦截Action调用的对象,它提供了一种机制可以使开发者在一个Action执行的前后执行一段代码,也可以在一个Action执行前阻止其执行,同时也提供了 ...
- java 中的拦截器和过滤器
区别: 1.拦截器是基于java的反射机制的,而过滤器是基于函数回调 2.过滤器依赖与servlet容器,而拦截器不依赖与servlet容器 3.拦截器只能对action请求起作用,而过滤器则可以对几 ...
- Springboot 拦截器配置(登录拦截)
Springboot 拦截器配置(登录拦截) 注意这里环境为springboot为2.1版本 1.编写拦截器实现类,实现接口 HandlerInterceptor, 重写里面需要的三个比较常用的方 ...
随机推荐
- Pollution over East China : Image of the Day
acquired October 16, 2002download large image (2 MB, JPEG, 6000x4600) acquired October 16, 2002downl ...
- JSP判断移动设备
日期: 2014年3月6日 人员::铁锚 看到了一篇很好的文章, <在天猫,前端做什么?>,里面有天猫php判断移动设备的正则(个人猜测),觉得很好用,于是就决定移植到JSP里面. jsp ...
- 网站论坛同步用户,整合api,实现…
在网上参考了很多资料后,终于完美实现了网站和discuz!nt论坛的双向整合,整合后网站和论坛之间可以同步注册.登录.退出和修改登录密码操作. 本系统的实现形式是新云CMS网站(ASP)和Discuz ...
- linux下用gtk+写比赛赌博GUI小游戏
游戏界面全部由gtk的GUI完成,没有使用openGL之类的高端货. 游戏玩法就是8位选手比赛跑步,你可以在赛前赌哪位选手会赢,如果输了cash会被扣除,反之cash会增加. 无聊写了3个选项:小数时 ...
- 二分算法C实现
#include <stdio.h> #include <stdlib.h> #define NR(x) (sizeof(x)/sizeof(x[0])) int Binary ...
- android 自定义相机
老规矩,先上一下项目地址:GitHub:https://github.com/xiangzhihong/CameraDemo 方式: 调用Camera API 自定义相机 调用系统相机 由于需求不同, ...
- Hash函数
简介 哈稀函数按照定义可以实现一个伪随机数生成器(PRNG),从这个角度可以得到一个公认的结论:哈希函数之间性能的比较可以通过比较其在伪随机生成方面的比较来衡量. 一些常用的分析技术,例如泊松分布可用 ...
- HBase中缓存的优先级
ava代码 // Instantiate priority buckets BlockBucket bucketSingle = new BlockBucket(bytesToFree, bloc ...
- 本人在CSDN上的技术博客访问量突破了10万次,特此截图留念
从 2011-11-16在CSDN开博至今,将近三年. 在近三年的时间里,本博的访问量于2014-07-01突破了10万次,单篇博文<软件开发高手须掌握的4大SQL精髓 ...
- OVS 中的哈希表: shash
shash出现在OVS的代码中,定义如下: struct hmap_node { size_t hash; struct hmap_node * next; }; struct ...