首页 > 技术文章 > SpringBoot+Mybatis+PostMan(五):token登陆认证过程二(redis缓存引入)

yeyuting 2021-01-18 17:58 原文

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项目中。

至此,结束。 

推荐阅读