SpringBoot+Mybatis+PostMan(五):token登陆认证过程二(redis缓存引入)
Springboot+Mybatis+redis+postman项目实战总目录*
SpringBoot+Mybatis+PostMan(六):token登陆认证过程三(redis封装与干掉原来session,避免用户重复登陆)
番外篇:SpringBoot 用户注册时经MD5加密存入数据库
第二篇章:用户角色权限访问控制
SpringBoot+Mybatis+PostMan(七):用户角色权限访问控制入门(数据模拟实现,不带数据库)
SpringBoot+Mybatis+PostMan(八):用户角色权限访问控制一(数据库用户角色表查询组合)
SpringBoot+Mybatis+PostMan(九):用户角色权限访问控制二(加入资源表和资源角色对应表)
SpringBoot+Mybatis+PostMan(十):用户角色权限访问控制三(禁用session、启用token并集成redis)
继上一篇博文,接着嵌入redis缓存,其实在上一篇博文中,用cookie实现拦截比较的不容易,因为对于postman来说,我们在实现增删改查的时候已经对每个端口进行了访问,也都生成了其自己对应的token与cookie中,这样一来,我们设置的拦截器其实就形同虚设了,这时就需要创建一个全新的缓存用于存储token,用于存储redis,同时还要方便于访问,这样一来我们自然就想到了redis,这篇博文咱们就来介绍如何将redis嵌入springboot项目,同时实现token认证与登陆。
项目代码获取地址:https://github.com/yeyuting-1314/testdemo_redis_DM5_insert_page_token.git
一、 准备工作
需要的安装工具见网盘连接:
链接:https://pan.baidu.com/s/1Pkdnn8kfu6SZESEfYqFWkQ
提取码:nsdj
1. 首先时redis的安装和配置,这里我们之前有写了十分详细的介绍,详情借鉴博文:https://www.cnblogs.com/yeyuting/p/14206888.html
2. redis安装好了后,为方便我们自己看redis缓存中中有哪些数据,我们安装一个redis可视化工具,安装包见上面的网页链接。
可视化工具安装步骤很简单,一直下一步即可,最后进入redis可视化页面,在“用户名”处填入“localhost”,测试一下连接,成功。
二、准备工作准备完毕,接下来接着前面代码继续修改。
1. 导入redis依赖
<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency>
2.常量Constants类添加两个常量
/* * redis存储token设置的过期时间 * */ public static final Integer TOKEN_EXPIRE_TIME =60*2 ; /* * 设置可以重置token过期时间的时间界限 * */ public static final Integer TOKEN_RESET_TIME =1000*100 ;
3. 拦截器也要进行相关改进
@Override public boolean preHandle (HttpServletRequest request , HttpServletResponse response , Object o )throws Exception{ //黑名单 有token 没有token //从request请求头里面获取 // String token = tokenUtil.getToken(request) ; //检查请求中是否存在token , 如果不存在就直接跳转到登陆页面 String token = request.getHeader("token") ; Jedis jedis = new Jedis("localhost" , 6379) ; if(StringUtil.isEmpty(token)){ System.out.println("不存在token"); response.sendRedirect("/login"); return false ; } String username = "" ; username = jedis.get(token) ; System.out.println("redis中用户信息值为:" + jedis.get(token)); if(username != null && !username.trim().equals("")){ System.out.println("token值匹配成功!"); Long tokenBirthTime = Long.valueOf(jedis.get(username+token)) ; Long diff = System.currentTimeMillis() - tokenBirthTime ; if (diff > Constants.TOKEN_RESET_TIME){ jedis.expire(username , Constants.TOKEN_EXPIRE_TIME) ; jedis.expire(token , Constants.TOKEN_EXPIRE_TIME) ; System.out.println("token 有效时间成功更新"); Long newBirthTime =System.currentTimeMillis(); jedis.set(token+username , newBirthTime.toString()) ; } return true ; } response.sendRedirect("/login"); return false ; }
4. controller层增加一个接口
@PostMapping("/loginWithRedis") @ResponseBody public Result loginWithRedis(@RequestBody User user){ Result result = userService.loginWithRedis(user) ; return result ; }
5. service层
public Result loginWithRedis(User user ) ;
public Result loginWithRedis(User user ){ User user1 = userMapper.selectByName(user.getUserName()) ; if(user1 == null ){ //response.sendRedirect("/login"); return Results.failure("用户不存在,") ; } if(!user1.getPassword().equals(user.getPassword())){ return Results.failure("密码输入错误") ; } Jedis jedis = new Jedis("localhost" , 6379) ; String token = tokenUtil.generateToken(user1) ; user1.setToken(token); jedis.set(user1.getUserName() , token) ; jedis.expire(user1.getUserName() , Constants.TOKEN_EXPIRE_TIME) ; jedis.set(token , user1.getUserName()) ; jedis.expire(token , Constants.TOKEN_EXPIRE_TIME) ; Long currentTime =System.currentTimeMillis() ; jedis.set(user1.getUserName()+token , currentTime.toString()) ; //用完关闭 jedis.close(); System.out.println("redis中token值为:" + jedis.get(user1.getUserName())); System.out.println("redis中用户信息值为:" + jedis.get(token)); return Results.successWithData(user1) ; }
这样一来,代码逻辑部分就完成了,接下来是模拟前端部分
三、前端呈现。
1. 如果对loginWithRedis端口进行拦截设置
拦截设置在MVCConfig类中设置:
@Override public void addInterceptors (InterceptorRegistry registry){ registry.addInterceptor(authenticationInterceptor()) //表示拦截所有请求 .addPathPatterns("/*") //表示取消对特定路径的拦截 .excludePathPatterns("/login") .excludePathPatterns("/loginCheck") ; //.excludePathPatterns("/loginWithRedis") ; //.excludePathPatterns("/selectOne") //这里一定不要写成/**/*.js的形式,spring boot无法识别 //取消对static目录下静态资源的拦截 // .excludePathPatterns("/static/**") ; }
前端模拟:
这时显示结果是不让通行,并将其拦截到登陆页面。
2. 如果不拦截此接口:
拦截设置在MVCConfig类中设置:
@Override public void addInterceptors (InterceptorRegistry registry){ registry.addInterceptor(authenticationInterceptor()) //表示拦截所有请求 .addPathPatterns("/*") //表示取消对特定路径的拦截 .excludePathPatterns("/login") .excludePathPatterns("/loginCheck") .excludePathPatterns("/loginWithRedis") ; //.excludePathPatterns("/selectOne") //这里一定不要写成/**/*.js的形式,spring boot无法识别 //取消对static目录下静态资源的拦截 // .excludePathPatterns("/static/**") ; }
前端模拟如上,启动项目,postman前端显示如下:
控制台显示如下:
这时redis可视化界面显示如下:
这样一来我们发现redis中已经存储好了wct对应的token值,将token值记录下来,下面我们要用此token值进行测试。
3. 在进行一次顺利的登陆后,再次拦截此端口,理想情况是用同样的信息登陆,这次能登陆进去(因为此用户已经登陆过一次,后面就不会被拦截了,即使我们对此端口进行了拦截,拦截方法中代码逻辑允许它通过)
拦截设置在MVCConfig类中设置:
@Override public void addInterceptors (InterceptorRegistry registry){ registry.addInterceptor(authenticationInterceptor()) //表示拦截所有请求 .addPathPatterns("/*") //表示取消对特定路径的拦截 .excludePathPatterns("/login") .excludePathPatterns("/loginCheck") //.excludePathPatterns("/loginWithRedis") ; //.excludePathPatterns("/selectOne") //这里一定不要写成/**/*.js的形式,spring boot无法识别 //取消对static目录下静态资源的拦截 // .excludePathPatterns("/static/**") ; }
前端进行模拟实现,在除了body中内容外,还要对header进行token值注入,以为我们在上面一种方法中返回给了前端postman对应的token值,需要前端人员将token值放到header中,但是我们并没有专门的前端人员进行前端数据处理,这样一来就需要我们自己手工加入里面,表示我们第一次已经访问了,并且也生成了token值,这时在拦截的方法中进行前端token值与redis中wct对应的token值匹配,匹配通过就给通过,匹配失败就拦截下来。
启动项目,访问端口,结果如下:
postman前端显示:
控制台输出:
这样一来,就完成了所有测试,redis也就完整的嵌入到了spring boot项目中。
至此,结束。