帮助中心/最新通知

质量为本、客户为根、勇于拼搏、务实创新

< 返回文章列表

【服务器相关】Redis实现短信登录的企业实战

发表时间:2025-09-24 16:09:00 小编:主机乐-Yutio

一、导入黑马点评项目

黑马点评项目主要包括以下功能:

这一章主要介绍短信登录功能,短信登录功能是基于Redis的共享session实现的

1. 导入SQL

需要项目资料的私信我

其中的表有:

  • tb_user:用户表
  • tb_user_info:用户详情表
  • tb_shop:商户信息表
  • tb_shop_type:商户类型表
  • tb_blog:用户日记表(达人探店日记)
  • tb_follow:用户关注表
  • tb_voucher:优惠券表
  • tb_voucher_order:优惠券的订单表

注意:Mysql的版本采用5.7及以上版本

2. 前后端分离

3. 导入后端项目

3.1 将后端项目导入到 Idea 中

3.2 注意:修改application.yaml文件中的mysql、redis地址信息 将mysql、redis地址信息修改为自己的信息

3.3 启动项目 启动项目后,在浏览器访问:http://localhost:8081/shop-type/list ,如果可以看到数据则证明运行没有问题

4. 导入前端项目

4.1 导入nginx文件夹 将nginx文件夹复制到任意目录,要确保该目录不包含中文、特殊字符和空格,例如:

4.2 运行前端项目 在nginx所在目录下打开一个CMD窗口,输入命令启动nginx:

start nginx.exe

打开chrome浏览器,在空白页面点击鼠标右键,选择检查,即可打开开发者工具:

然后访问: http://127.0.0.1:8080 ,即可看到页面:

二、基于Session实现登录流程

  • 后端将生成的验证码和用户信息保存到session中,并将sessionId返回给前端保存到cookie中
  • 用户登录时,会携带cookie向后端发起请求,后端进行校验时,从cookie中获取sessionId,通过sessionId可以从session中获取用户信息并保存到ThreadLocal中
  • 后续每个线程都有一份ThreadLocal中的用户副本信息,不同线程拿到用户信息后可以实现不同的操作,从而起到线程隔离作用

1. 发送短信验证码

主要代码:

主要代码:

UserController

为了避免用户请求每个controller时,每次都去校验用户信息,所以可以加拦截器

拦截器只需在用户请求访问时,校验一次后将用户信息保存到ThreadLocal中,供后续线程使用

主要代码:

在工具类中编写ThreadLocal

四、基于Redis实现共享session的登录功能

1. 选择合适的数据结构存入Redis

  • 手机号作为key,String类型的验证码作为value
  • 用户登录时正好会提交手机号,方便通过Redis进行校验验证码

token作为key,Hash类型的用户信息作为value

后端校验成功后,会返回token给前端,前端会将token保存到sessionStorage中(这是浏览器的存储方式),以后前端每次请求都会携带token,方便后端通过Redis校验用户信息

前端代码:将后端返回的token保存到sessionStorage中

前端每次请求时,都会通过拦截器将token设置到请求头中,赋值给变量authorization,后端通过authorization获取前端携带的token进行校验

2. 发送短信验证码

修改之前代码,将验证码存入Redis

刷新token的拦截器代码:


public class RefreshTokenInterceptor implements HandlerInterceptor {

// 因为LoginInterceptor不是通过Spring进行管理的Bean,所以不能再LoginInterceptor中进行注入StringRedisTemplate
// 可以通过构造方法传入StringRedisTemplate
private StringRedisTemplate stringRedisTemplate;

public RefreshTokenInterceptor(StringRedisTemplate stringRedisTemplate) {
this.stringRedisTemplate = stringRedisTemplate;
}


@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//// 1.获取session
//HttpSession session = request.getSession();
//// 2.获取session中的用户
//Object user = session.getAttribute(“user”);
//// 3.判断用户是否存在
//if(user == null){
//// 4.不存在,拦截,返回401状态码
//response.setStatus(401);
//return false;
//}
//// 5.存在,保存用户信息到ThreadLocal
//UserHolder.saveUser((UserDTO)user);
//// 6.放行
//return true;

// 1.获取请求头中的token
String token = request.getHeader(“authorization”);
if (StrUtil.isBlank(token)) {
// 不存在,则拦截,返回401状态码
response.setStatus(401);
return false;
}

// 2.通过token获取redis中的用户
Map<Object, Object> userMap = stringRedisTemplate.opsForHash()
.entries(RedisConstants.LOGIN_USER_KEY + token);

// 3.判断用户是否存在
if (userMap.isEmpty()) {
// 4.用户不存在,则拦截,返回401状态码
response.setStatus(401);
return false;
}

// 5.将redis中Hash类型数据转换成UserDTO对象
UserDTO userDTO = BeanUtil.fillBeanWithMap(userMap, new UserDTO(), false);

// 6.用户存在,保存用户信息到ThreadLocal
UserHolder.saveUser(userDTO);

// 7.刷新token有效期
stringRedisTemplate.expire(RedisConstants.LOGIN_USER_KEY + token, RedisConstants.LOGIN_USER_TTL, TimeUnit.MINUTES);

// 8.放行
return true;
}


@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
// 请求结束后移除用户,防止ThreadLocal造成内存泄漏
UserHolder.removeUser();
}
}

登录拦截器的代码:


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;
}

}


@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刷新的拦截器,order越小,执行优先级越高,所以token刷新的拦截器先执行
registry.addInterceptor(new RefreshTokenInterceptor(stringRedisTemplate)).addPathPatterns(“/**”)
.excludePathPatterns(
// RefreshTokenInterceptor拦截器也需要放行”/user/code”,”/user/login”,不然token过期后再重新登录就会一直被拦截
“/user/code”,
“/user/login”)
.order(0);
}
}

到此这篇关于Redis实现短信登录的企业实战的文章就介绍到这了,更多相关Redis 短信登录 内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!


联系我们
返回顶部