我们经常会遇到这样的事情,我们登录某个网页只可以浏览,点击某些操作时他就会提示我们用户未登录,或者是登录好了长时间不操作,提示我们登录超时请重新登录。其实这两种都可以用过滤器+Redis来简单实现,下面我们简单实现一种,“长时间不操作,提示我们登录超时请重新登录”。
token令牌:是服务端生成的一串随机生成字符串(我们的例子用UUID生成即可),放在请求头作为客户端进行请求的一个标识。 当用户第一次登录,服务器生成一个token并将此token返回给客户端,以后客户端只需带上这个token前来请求数据即可判断是谁在调用接口,无需再要用户名密码等。
localStorage:用于长久全局保存整个客户端网站的数据,没有过期时间,知道手动删除。也就是把值存到里面后,在任何一个客户端网页都可以取到他们的值。可以用来存登录成功后:显示欢迎xxx!
存值:localstorage.setItem("name","value") 简写:localstorage.name = "value"。
取值:localstorage.getItem("name") 简写:value = localstorage.name。
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
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("过滤器已经死亡!");
}
}
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;
}
}
1.index.html:登录页面
2.show.html:操作页面
登录
主页面
你的具体信息如下: