基于Session实现短信登录
创始人
2024-04-02 20:55:55
0

目录

一、基于Session实现登录

1.1 业务流程图​编辑

二、发送短信验证码

2.1 发送短信请求方式及参数说明

2.2 业务层代码模拟发送短信

三、登录功能

 3.1  短信验证的请求方式及路径

3.2  业务层代码实现用户登录

3.3 拦截器——登录验证功能

三、隐藏用户敏感信息

四、session共享问题


一、基于Session实现登录

1.1 业务流程图

二、发送短信验证码

2.1 发送短信请求方式及参数说明

这个地方为什么需要session?  因为我们需要把验证码保存在session当中

/*** 发送手机验证码*/@PostMapping("code")public Result sendCode(@RequestParam("phone") String phone, HttpSession session) {// TODO 发送短信验证码并保存验证码
//        return Result.fail("功能未完成");return userService.sendCode(phone,session);}

2.2 业务层代码模拟发送短信

    @Overridepublic Result sendCode(String phone, HttpSession session) {
//      1.校验手机号if(RegexUtils.isPhoneInvalid(phone)){
//              说明:RegexUtils使我们封装的一个类   isCodeInvalid是里面的静态方法,在这个静态方法里面又调用了另外一个静态方法得以实现
//      2.如果不符合,返回错误信息return Result.fail("手机号格式错误");}//      3.符合,生成验证码    6代表生成的验证码的长度  RandomUtil使用这个工具类生成String code =  RandomUtil.randomNumbers(6);
//      4.保存验证码到session       key必须是一个字符串,value是一个对象session.setAttribute("code",code);
//      5.发送验证码
//        实现起来比较麻烦 我们使用日志假装发送log.debug("发送短信验证码成功,验证码:"+code);return Result.ok();}
}

三、登录功能

 3.1  短信验证的请求方式及路径

    /*** 登录功能* @param loginForm 登录参数,包含手机号、验证码;或者手机号、密码*/@PostMapping("/login")public Result login(@RequestBody LoginFormDTO loginForm, HttpSession session){// TODO 实现登录功能return userService.login(loginForm,session);}

3.2  业务层代码实现用户登录

流程图:

代码:

/*** 实现用户登录* @param loginForm  登录的参数* @param session* @return*/@Overridepublic Result login(LoginFormDTO loginForm, HttpSession session) {
//      1.校验手机号if(RegexUtils.isPhoneInvalid(loginForm.getPhone())){
//              说明:RegexUtils使我们封装的一个类   isCodeInvalid是里面的静态方法,在这个静态方法里面又调用了另外一个静态方法得以实现
//          1.2.如果不符合,返回错误信息return Result.fail("手机号格式错误");}
//      2.校验验证码
//           2.1 得到code 这个值是真实的codeObject cacheCode = session.getAttribute("code");
//           2.2 获取用户输入的codeString code = loginForm.getCode();if(cacheCode ==null || !cacheCode.toString().equals(code)){
//      3.不一致,报错return Result.fail("验证码错误");}//      4.一致,根据手机号查询用户   .one()代表查询一个  list()代表着查询多个User user =query().eq("phone",loginForm.getPhone()).one();//      5.判断用户是否存在if(user ==null){
//      6.不存在,创建新用户并保存user = createUserWithPhone(loginForm.getPhone());}//      7.保存用户信息到session中session.setAttribute("user",user);return Result.ok();}private User createUserWithPhone(String phone) {
//      1.创建用户User user = new User();user.setPhone(phone);
//       USER_NICK_NAME_PREFIX其实就是 "user_",这样写更有逼格user.setNickName(USER_NICK_NAME_PREFIX+RandomUtil.randomString(10));
//        保存用户save(user);return user;}

3.3 拦截器——登录验证功能

// HandlerInterceptor 这是一个拦截器
public class LoginInterceptor implements HandlerInterceptor {
//  前置拦截   在进入controller之前我们进行登录校验@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//      1.获取sessionHttpSession session  =request.getSession();
//      2.获取session中的用户Object user = session.getAttribute("user");
//      3.判断用户是否存在if(user == null){// 4.不存在,拦截response.setStatus(401);  //返回401状态码return false;}
//      5.存在,保存用户信息到ThreadLocal  保存在当前线程里面的UserHolder.saveUser((User)user);
//      6.放行return true;}
//  在controller执行之后拦截  这个我们在这里不需要
//    @Override
//    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
//        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
//    }//  渲染之后,返回给用户之前   用户业务执行完毕我们要销毁维护信息,避免泄露@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
//      移除用户UserHolder.removeUser();}
}
public class UserHolder {private static final ThreadLocal tl = new ThreadLocal<>();public static void saveUser(User user){tl.set(user);}public static User getUser(){return tl.get();}public static void removeUser(){tl.remove();}
}
@Configuration
public class MvcConfig implements WebMvcConfigurer {//  拦截器的注册器@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new LoginInterceptor()).excludePathPatterns("/user/code","/user/login","/shop/**","/blog/hot","/shop-type/**","upload/**","voucher/**");}
}
    @GetMapping("/me")public Result me(){// TODO 获取当前登录的用户并返回
//        直接取就可以了User user=  UserHolder.getUser();return Result.ok(user);}

三、隐藏用户敏感信息

如下图所示,服务器返回的信息有点多,我们为了保护用户的信息,我们需要隐藏部分的内容

所以一开始我们存入session的信息就不应该是完整的信息,这样才能降低服务器的压力

UserServiceImpl中的login方法

//      7.保存用户信息到session中   \
//         BeanUtil.copyProperties(user, UserDTO.class))  会自动的将user中的属性拷贝到UserDTO当中而且也创建出一个UserDTO对象session.setAttribute("user", BeanUtil.copyProperties(user, UserDTO.class));

取的时候我们也应该做出变化

LoginInterceptor类
//      5.存在,保存用户信息到ThreadLocal  保存在当前线程里面的UserHolder.saveUser((UserDTO)user);

此时我们再登录查询信息,就还剩下三个字段了

四、session共享问题

多台Tomcat并不共享session存储空间,当请求切换到不同的Tomcat服务导致数据丢失的问题

所以这个方案就被pass了

session的替代方案应该满足:

  • 数据共享
  • 内存存储
  • key、value结构

所以我们选择Redis

任何一台Tomcat都能访问到Redis,这样就能实现数据共享

有兴趣的朋友可以再对比一下Redis实现短信登录,两个对比学习

Redis替代Session实现用户短信登录(超级详细解释)_我爱布朗熊的博客-CSDN博客

相关内容

热门资讯

保存时出现了1个错误,导致这篇... 当保存文章时出现错误时,可以通过以下步骤解决问题:查看错误信息:查看错误提示信息可以帮助我们了解具体...
汇川伺服电机位置控制模式参数配... 1. 基本控制参数设置 1)设置位置控制模式   2)绝对值位置线性模...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
不一致的条件格式 要解决不一致的条件格式问题,可以按照以下步骤进行:确定条件格式的规则:首先,需要明确条件格式的规则是...
本地主机上的图像未显示 问题描述:在本地主机上显示图像时,图像未能正常显示。解决方法:以下是一些可能的解决方法,具体取决于问...
表格列调整大小出现问题 问题描述:表格列调整大小出现问题,无法正常调整列宽。解决方法:检查表格的布局方式是否正确。确保表格使...
表格中数据未显示 当表格中的数据未显示时,可能是由于以下几个原因导致的:HTML代码问题:检查表格的HTML代码是否正...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...