SpringBoot+过滤器filter+Redis实现最简单的token登录令牌

我们经常会遇到这样的事情,我们登录某个网页只可以浏览,点击某些操作时他就会提示我们用户未登录,或者是登录好了长时间不操作,提示我们登录超时请重新登录。其实这两种都可以用过滤器+Redis来简单实现,下面我们简单实现一种,“长时间不操作,提示我们登录超时请重新登录”。

了解几个概念

token令牌:是服务端生成的一串随机生成字符串(我们的例子用UUID生成即可),放在请求头作为客户端进行请求的一个标识。 当用户第一次登录,服务器生成一个token并将此token返回给客户端,以后客户端只需带上这个token前来请求数据即可判断是谁在调用接口,无需再要用户名密码等。

SpringBoot+过滤器filter+Redis实现最简单的token登录令牌_第1张图片

localStorage:用于长久全局保存整个客户端网站的数据,没有过期时间,知道手动删除。也就是把值存到里面后,在任何一个客户端网页都可以取到他们的值。可以用来存登录成功后:显示欢迎xxx!

存值:localstorage.setItem("name","value")  简写:localstorage.name = "value"。

取值:localstorage.getItem("name")              简写:value = localstorage.name。  

步骤1:springboot整合Redis,MySQL,Mybatis

1.pom依赖



    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        2.7.5
         
    
    com.zx.token
    demo
    0.0.1-SNAPSHOT
    token_test
    Demo project for Spring Boot
    
        1.8
    
    
        
        
            org.springframework.boot
            spring-boot-starter
        

        
            org.springframework.boot
            spring-boot-starter-test
            test
        
        
        
            org.springframework.boot
            spring-boot-starter-jdbc
        
        
            mysql
            mysql-connector-java
            8.0.30 
            runtime
        

        
        
            com.alibaba
            druid
            1.2.5
        

        
        
            org.mybatis.spring.boot
            mybatis-spring-boot-starter
            2.2.2
        

        
        
            org.projectlombok
            lombok
            1.18.10
            provided
        

        
        
            com.alibaba
            fastjson
            1.2.35
        

        
        
            org.springframework.boot
            spring-boot-starter-web
        

        
        
            redis.clients
            jedis
            3.2.0
        

        
        
            org.springframework.boot
            spring-boot-starter-data-redis
        
        
        
            org.apache.commons
            commons-pool2
        

        
        
            junit
            junit
        

    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    


2.yml文件配置

spring:
  #MySQL配置
  datasource:
    username: root
    password: 123
    url: jdbc:mysql://localhost:3306/zx?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
    type: com.alibaba.druid.pool.DruidDataSource

    #Redis配置
  redis:
    host: 127.0.0.1
    port: 6379
    database: 0  #连接的是那个库一共16个0~15,默认0
    
    #mybatis配置及取别名
mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.zx.token.entity

步骤2:写过滤器

1.FilterConfig:注册过滤器,并声明过滤条件(声明)。

2.MyFilter:经过过滤器需要执行的具体业务(如何处理)。(主要是doFilter方法)

package com.zx.token.config;

import com.zx.token.filter.MyFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FilterConfig {
    @Autowired
    MyFilter myFilter;

    @Bean
    public FilterRegistrationBean filterRegistrationBean(){
        //注册过滤器(初始化过滤器)
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(myFilter);

        //添加过滤的路径,凡是路径带/user就进入过滤器
        filterRegistrationBean.addUrlPatterns("/user/*");

        return filterRegistrationBean;
    }
}
package com.zx.token.filter;


import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

@Component
public class MyFilter implements Filter {

    @Resource //作用和@Autowired,只是他按名字注入,而@Autowired按类型注入
    private RedisTemplate redisTemplate;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("-----------------过滤器初始化----------------");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
       //校验用户登录状态
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        System.out.println("执行过滤器");
        //取出token
        String token = request.getHeader("token");
        //第一次登录没有token,给null会报错,所以我们判断一下token是否为空,为空给一个空串
        //三元运算
        token = token==null?"":token;
        //查询Redis中token的剩余时间
        Long expire =redisTemplate.getExpire(token);
        if(expire > 0){
            //时间大于0 放行
            /*
            有一个问题,用户一直在网页上操作,但是token一直在倒计时,操作着操作着就变未登录了
            不合理,所以,当用户在操作时,每次经过过滤器调用不同接口时,就重置一下token的时间
             */
            redisTemplate.expire("token",1L, TimeUnit.MINUTES);
            //放行
            filterChain.doFilter(servletRequest,servletResponse);
        }else {
            System.out.println("未登录!");
            return;
        }
    }

    @Override
    public void destroy() {
        System.out.println("过滤器已经死亡!");
    }
}

步骤3:controller层,主要在该层操作,其他层的正常书写。

package com.zx.token.controller;

import com.alibaba.fastjson.JSON;
import com.zx.token.entity.User;
import com.zx.token.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.Duration;
import java.util.UUID;

@RestController
public class UserController {
   @Autowired
   UserService service;

   @Resource //作用和@Autowired,只是他按名字注入,而@Autowired按类型注入
   private RedisTemplate redisTemplate;

    @RequestMapping("/login")
    public String login(User luser,HttpServletRequest request){
        User user = service.login(luser.getName(),luser.getPsd());
        if(user!=null){
            //生成一个token令牌 用UUID生成一个唯一标识
            String token = UUID.randomUUID()+"";
            //存到Redis中
            redisTemplate.opsForValue().set(token,user, Duration.ofMinutes(1L));

            return token;
        }
            return null;
    }

    @RequestMapping("/user/use")
    public String getUserOfLogin(HttpServletRequest request){
        //获取请求头中的token参数
        String token = request.getHeader("token");
        User user = (User) redisTemplate.opsForValue().get(token);
        if (user!=null){
            String jsonString = JSON.toJSONString(user);
            return jsonString;
        }
            return null;
    }
}

步骤4:用HTML测试效果。

1.index.html:登录页面

2.show.html:操作页面




    
    
    登录


  
用户名:
密 码:




    
    
    主页面


   

你的具体信息如下:



测试效果  

SpringBoot+过滤器filter+Redis实现最简单的token登录令牌_第2张图片

SpringBoot+过滤器filter+Redis实现最简单的token登录令牌_第3张图片 SpringBoot+过滤器filter+Redis实现最简单的token登录令牌_第4张图片

 

数据库就一张表三个数据,需要测试随便建个数据表即可

需要这个小例子源码的可以去我的Gitee拉取。

点击获取克隆地址~~~

你可能感兴趣的:(java,数据库,开发语言,spring,boot)