基于session实现短信登陆
ThreadLocal就是一个线程域对象,在我们的业务当中每一个请求到达服务都会是一个独立的线程,如果说我们没有用ThreadLocal而是直接把用户保存到本地变量,那么可能会出现多线程并发修改的一个安全问题,而ThreadLocal会将数据保存到每一个线程的内部,在线程内部创建一个map去保存,这样一来每个线程都有自己独立的存储空间,那每一个请求来了之后都有自己的空间,相互之间没有干扰
生成六位随机数
RandomUtil.randomNumbers(6)
生成10位随机字符串
RandomUtil.randomString(10)
验证登录功能:
拦截器类:
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 1.判断是否需要拦截(ThreadLocal中是否有用户)
if (UserHolder.getUser() == null) {
// 没有,需要拦截,设置状态码
response.setStatus(401);
// 拦截
return false;
}
// 有用户,放行
return true;
}
}
在MvcConfig中配置拦截器:
@Configuration
public class MvcConfig implements WebMvcConfigurer {
@Resource
private StringRedisTemplate stringRedisTemplate;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 登录拦截器
registry.addInterceptor(new LoginInterceptor())
.excludePathPatterns(
"/shop/**",
"/voucher/**",
"/shop-type/**",
"/upload/**",
"/blog/hot",
"/user/code",
"/user/login"
).order(1);
// token刷新的拦截器
registry.addInterceptor(new RefreshTokenInterceptor(stringRedisTemplate)).addPathPatterns("/**").order(0);
}
}
使用工具类将user对象转为useDTO对象:
BeanUtil.copyProperties(user, UserDTO.class)
集群session会有共享问题,部署到集群多台tomcat并不共享session存储空间,当请求切换到不同服务器会出现数据丢失的情况。session的替代方案是redis。
基于redis实现session登录