①实现基于session的登录流程:发送验证码、登录注册、校验登陆状态

在这里插入图片描述

个人简介:Java领域优质创作者;阿里云技术博主、星级博主、专家博主;正在Java学习的路上摸爬滚打,记录学习的过程~
个人主页:.29.的博客
学习社区:进去逛一逛~

在这里插入图片描述

登录功能 实现

  • 实现基于session的登录流程:发送验证码、登录注册、校验登陆状态
    • 🚀流程介绍
      • ①验证码发送
      • ②用户登录、注册
      • ③校验登录状态
    • 🚀代码实现


实现基于session的登录流程:发送验证码、登录注册、校验登陆状态


🚀流程介绍

登录流程

①验证码发送

  • 发送验证码

    • 用户输入手机号,点击发送按钮进行手机号提交,程序会校验手机号是否合法,不合法时要求用户重新输入手机号,合法则在后台生成对应的验证码并保存至session,之后通过短信方式将验证码发送给用户。

      • 什么是HttpSession?

      • HttpSession是Java Web中的一个接口,它提供了一种在服务器端存储和检索用户相关信息的机制。当用户第一次访问Web应用程序时,服务器会为该用户创建一个唯一的session ID,并将该ID存储在一个名为JSESSIONID的cookie中,然后将该ID与一个新的HttpSession对象相关联。在用户与Web应用程序交互期间,可以使用HttpSession对象来存储和检索与该用户相关的信息。当用户关闭浏览器或超过session超时时间时,session对象将被销毁。

        以下是获取和使用HttpSession对象的常用方法:

        1.获取HttpSession对象:

         HttpSession session = request.getSession();
        

        2.向session中存储数据:

         session.setAttribute("key", value);
        

        3.从session中获取数据:

         Object value = session.getAttribute("key");
        

        4.从session中删除数据:

         session.removeAttribute("key");
        

        5.使session失效:

         session.invalidate();
        

②用户登录、注册

  • 注册、登录
    • 用户将手机号、验证码输入,后台从session中获取验证码与用户输入的验证码进行比对校验,如果不一致则无法通过校验,提示用户验证码错误,验证码一直则后台根据手机号查询用户,若用户不存在,则为用户创建账号信息并保存至数据库中,最后无论用户是否存在,都将用户的信息保存至session中,方便后续业务获取当前用户信息。

③校验登录状态

  • 校验登陆状态

    • 用户在客户端发起请求时,Cookie会携带用户的 JsessionId 后台,后台根据 JsessionId 从session中获取用户信息,如果没有用户信息就表示未登录,会对请求进行拦截,如果有用户信息,将其存入到本地线程 ThreadLocal 中并放行。

      • 为什么使用ThreadLocal:

        • 每个用户其实对应都是去找tomcat线程池中的一个线程来完成工作的, 使用完成后再进行回收,既然每个请求都是独立的,所以在每个用户去访问我们的工程时,我们可以使用threadlocal来做到线程隔离,每个线程操作自己的一份数据。
      • 什么是 JsessionId ?

        • JSessionId是Java Web应用程序中的一个会话标识符,用于跟踪用户与Web应用程序之间的会话。当用户第一次访问Web应用程序时,服务器会为该用户创建一个唯一的JSessionId,并将其存储在cookie中。在随后的请求中,浏览器会将该cookie发送回服务器,以便服务器可以识别用户并维护会话状态。

          在Java Web应用程序中,可以使用HttpSession对象来访问和管理会话状态。




🚀代码实现

业务逻辑实现


  • 统一返回类型 实体类

    • @Data
      @NoArgsConstructor
      @AllArgsConstructor
      public class Result {private Boolean success;private String errorMsg;private Object data;private Long total;public static Result ok(){return new Result(true, null, null, null);}public static Result ok(Object data){return new Result(true, null, data, null);}public static Result ok(List<?> data, Long total){return new Result(true, null, data, total);}public static Result fail(String errorMsg){return new Result(false, errorMsg, null, null);}
      }



  • 校验手机号、邮箱、验证码格式

    • public class RegexUtils {/*** 是否是无效手机格式* @param phone 要校验的手机号* @return true:符合,false:不符合*/public static boolean isPhoneInvalid(String phone){return mismatch(phone, RegexPatterns.PHONE_REGEX);}/*** 是否是无效邮箱格式* @param email 要校验的邮箱* @return true:符合,false:不符合*/public static boolean isEmailInvalid(String email){return mismatch(email, RegexPatterns.EMAIL_REGEX);}/*** 是否是无效验证码格式* @param code 要校验的验证码* @return true:符合,false:不符合*/public static boolean isCodeInvalid(String code){return mismatch(code, RegexPatterns.VERIFY_CODE_REGEX);}// 校验是否不符合正则格式private static boolean mismatch(String str, String regex){if (StrUtil.isBlank(str)) { //Hutool工具:StrUtilreturn true;}return !str.matches(regex);}
      }



  • 发送短信验证码 业务

    •     @Overridepublic Result sendCode(String phone, HttpSession session) {//1. 手机号不合法?if(RegexUtils.isPhoneInvalid(phone)){//2. 不合法,返回错误信息return Result.fail("手机号格式错误!");}//3. 借助工具类,生成验证码(Hutool工具)String code = RandomUtil.randomNumbers(6);//4. 保存验证码至session域session.setAttribute("code",code);//5. 发送验证码log.debug("发送短信验证码成功,验证码: " + code);  //日志、方便控制台查看/*调用验证码服务...(具体逻辑参照具体服务供应商的文档)*///6. 返回okreturn Result.ok();}
      



  • 登录、注册 业务

    •     /***   session实现登录功能* @param loginForm* @param session* @return*/@Overridepublic Result login(LoginFormDTO loginForm, HttpSession session) {//1. 校验手机号String phone = loginForm.getPhone();if(RegexUtils.isPhoneInvalid(phone)){//2. 返回错误信息return Result.fail("手机号格式错误");}//3. 校验验证码Object cacheCode = session.getAttribute("code");String code = loginForm.getCode();if(code == null || !code.toString().equals(cacheCode)){//不一致,返回错误信息return Result.fail("验证码错误");}// 一致,根据手机号获取用户User user = this.query().eq("phone", phone).one(); //(mybatisPlus提供的Service层方法)//5. 判断用户是否存在if(user == null){//6. 不存在,创建新用户user = new User();user.setPhone(phone); //设置phoneuser.setNickName(USER_NICK_NAME_PREFIX + RandomUtil.randomString(10)); //设置随机昵称this.save(user); // 存入数据库(mybatisPlus提供的Service层方法)}//7. 用户存在,存入session域session.setAttribute("user", BeanUtil.copyProperties(user, UserDTO.class));//返回okreturn Result.ok();}
      



  • 创建并设置ThreadLocal 自定义工具类

    • public class UserHolder {private static final ThreadLocal<UserDTO> tl = new ThreadLocal<>();public static void saveUser(UserDTO user){tl.set(user);}public static UserDTO getUser(){return tl.get();}public static void removeUser(){tl.remove();}
      }
      



  • 校验登陆状态 拦截器

    • /*** TODO 登录 拦截器* @author .29.* @create 2023-11-26 16:37*/public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 1.获取sessionHttpSession session = request.getSession();//2. 获取用户Object user = session.getAttribute("user");//3. 验证用户是否存在if(user == null){//4. 不存在,进行拦截,返回401状态码response.setStatus(401);return false;}//5. 存在,存入ThreadLocal(自定义工具类UserHolder,作用:创建并设置ThreadLocal)UserHolder.saveUser((UserDTO) user);//6. 放行return true;}}    
      
      • Spring Boot使用Spring MVC拦截器的步骤如下:

        • 1.创建一个拦截器类并实现HandlerInterceptor接口,该接口包含三个方法:preHandle、postHandle和afterCompletion。preHandle方法在请求处理之前调用,postHandle方法在请求处理之后调用,afterCompletion方法在视图渲染之后调用。

        • 2.在拦截器类上使用@Component@Configuration注解将其声明为Spring组件。

        • 3.创建一个配置类并实现WebMvcConfigurer接口,该接口包含一个addInterceptors方法,用于注册拦截器。

        • 4.在addInterceptors方法中使用addInterceptor方法注册拦截器,并使用addPathPatterns方法指定要拦截的请求路径。



  • 使拦截器生效 SpringMvc配置类

    • /*** TODO SpringMVC配置类,使拦截器生效* @author .29.* @create 2023-11-26 16:49*/
      @Configuration
      public class MvcConfig implements WebMvcConfigurer {@Resourceprivate StringRedisTemplate stringRedisTemplate;@Overridepublic void addInterceptors(InterceptorRegistry registry) {//1. 添加登录拦截器、同时设置无需拦截的路径registry.addInterceptor(new LoginInterceptor()).excludePathPatterns("/shop/**","/voucher/**","/shop-type/**","/upload/**","/blog/hot","/user/code","/user/login").order(0); //order默认0,order值越大拦截器越后执行}}




在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/177728.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

制作openeuler的livecd

下载该项目&#xff0c;执行下面的操作gitee openeuler livecd项目 基于openeuler环境 #安装工具&#xff0c;第一次可能报错&#xff0c;可以再执行一次 make installx86 livecd-creator -d -v --config./config/euler_x86_64.ks --fslabeleuler-LiveCD --cachecache --log…

HarmonyOS—ArkTS中@Observed和@ObjectLink装饰器的嵌套类对象属性变化【鸿蒙专栏-11】

文章目录 ARKTS中@Observed和@ObjectLink装饰器的嵌套类对象属性变化@Observed 类装饰器说明装饰器参数类装饰器的使用@ObjectLink 变量装饰器说明装饰器参数同步类型允许装饰的变量类型被装饰变量的初始值举例装饰器的限制条件观察变化和行为表现观察的变化框架行为使用场景1.…

docker安装各开发环境

docker安装 安装Docker # 环境安装&#xff1a; yum -y install gcc-c# 第一步&#xff1a;安装必要的一些系统工具 yum install -y yum-utils device-mapper-persistent-data lvm2# 第二步&#xff1a;添加软件源信息 yum-config-manager --add-repo http://mirrors.aliyun.…

没有哈希时间锁定合约的跨链原子交换

在上一篇文章中&#xff0c;我们介绍了使用哈希时间锁定合约&#xff08;HTLC&#xff09;的跨链原子交换实现。 今天&#xff0c;我们介绍一种无需 HTLC 即可实现的替代方法。 这将原子交换扩展到缺乏哈希锁和时间锁的区块链。 使用 SPV 证明交易已被挖掘 让我们按照商定的价…

windows10系统更新失败无法进入系统

用户反馈早上电脑重启&#xff0c;系统在更新卡好久好进去是否更新windows11&#xff0c;选否&#xff0c;重新就反复在更新中无法进入系统。我在测试的过程也是多次更新卡好久无法进入系统&#xff0c;而且出现下面提示 windows10系统更新失败无法进入系统&#xff0c;蓝屏提…

软件工程 课后题 acmakb 总结

让你一口气复习个爽&#xff01; 具体的应用题参考 软件工程学科出现的主要原因是软件危机的出现 20世纪60年代提出了软件工程的概念 软件危机的主要原因是软件本身的特点及开发方法 软件工程的三要素是方法、工具和过程 与计算机硬件相比&#xff0c;计算机软件有哪些特点…

设备管理的方法与思路

阅读本文你将了解设备管理的思路与方法&#xff1a;一、制定全面的管理计划&#xff1b;二、标准化管理流程&#xff1b;三、设备维护与保养&#xff1b;四、风险管理与预防&#xff1b;五、引入数字化工具。 设备管理在生产制造领域是保障生产安全和效率的核心环节。通过引入…

java分布式锁分布式锁

java分布式&锁&分布式锁 锁 锁的作用&#xff1a;有限资源的情况下&#xff0c;控制同一时间段&#xff0c;只有某些线程&#xff08;用户/服务器&#xff09;能访问到资源。 锁在java中的实现&#xff1a; synchronized关键字并发包的类 缺点&#xff1a;只对单个的…

强化学习中的“agent“

在强化学习中&#xff0c;"agent"&#xff08;智能体&#xff09;是指一个在环境中执行动作以达到某个目标的实体。强化学习是一种机器学习范式&#xff0c;其中智能体通过与环境的交互来学习最优的行为策略&#xff0c;以最大化累积的奖励信号。 以下是强化学习中 …

【Flutter】graphic图表的快速上手

简介 graphic是一个数据可视化语法和Flutter图表库。 官方github示例 网上可用资源很少,只有作者的几篇文章,并且没有特别详细的文档,使用的话还是需要一定的时间去调研,在此简单记录。 示例 以折线图为例(因为我只用到了折线图,但其他的图大差不差) 创建一个两个文…

邦芒宝典:职场中最重要的16种竞争力

​​职场竞争力包括哪几个方面&#xff0c;职场竞争力,简单地说,就是在职场中与他人相比&#xff0c;你所具备的优势及长处。以下小邦精心为大家准备了职场竞争力包括哪几个方面&#xff0c;快来一起看看吧。 ​1、技能和知识&#xff1a;具备相关的技能和知识&#xff0c;尤其…

世微 舞台灯深度调光 大功率 dc-dc降压恒流驱动IC APS54083

产品描述 APS54083 是一款 PWM 工作模式,高效率、外围简单、外置功率 MOS 管&#xff0c;适用于 5-220V 输入高精度降压 LED 恒流驱动芯片。输出最大功率150W最大电流 6A。APS54083 可实现线性调光和 PWM 调光&#xff0c;线性调光脚有效电压范围 0.5-2.5V.PWM 调光频率范围 10…

C++ :静态成员

静态成员 静态成员就是在成员变量和成员函数前加上关键字 static &#xff0c;称为静态成员 静态成员分为&#xff1a; 静态成员变量 1.所有对象共享同一份数据 2.在编译阶段分配内存 3.类内声明&#xff0c;类外初始化 静态成员函数 1.所有对象共享同一个函数 2.静态成…

HTTPS的安全问题及应对方案

HTTPS是一种在网络通信中广泛使用的安全协议&#xff0c;通过使用SSL/TLS加密来保护数据的传输。然而&#xff0c;即使在使用了HTTPS的情况下&#xff0c;仍然存在一些潜在的安全问题。本文将深入探讨HTTPS的安全问题&#xff0c;并提供一些有效的应对策略&#xff0c;以确保数…

CodeGeeX2模型安装

简介 CodeGeeX2 是多语言代码生成模型 CodeGeeX (KDD’23) 的第二代模型。不同于一代 CodeGeeX&#xff08;完全在国产华为昇腾芯片平台训练&#xff09; &#xff0c;CodeGeeX2 是基于 ChatGLM2 架构加入代码预训练实现&#xff0c;得益于 ChatGLM2 的更优性能&#xff0c;Co…

第29期 | GPTSecurity周报

GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区&#xff0c;集成了生成预训练Transformer&#xff08;GPT&#xff09;、人工智能生成内容&#xff08;AIGC&#xff09;以及大型语言模型&#xff08;LLM&#xff09;等安全领域应用的知识。在这里&#xff0c;您可以…

C# 实现微信退款及对帐

目录 需求 基础准备 关键代码 操作界面 ​编辑 退款订单类及方法 退款功能实现 对帐 支付商家后台相关要点 实时交易帐单查询 精确交易帐单查询 小结 需求 在招聘报名系统里&#xff0c;考务费支付是其中一个环节&#xff0c;支付方式很多种&#xff0c;比如银联、…

MySQL数据库 增删改查

目录 MySQL 数据插入 MySQL 数据删除 MySQL 数据更新 MySQL 数据查询 MySQL 联合查询 解决乱码问题 MySQL 数据插入 向MySQL数据表插入数据通用的 INSERT INTO SQL语法&#xff1a; INSERT INTO table_name ( field1, field2,...fieldN ) VALUES ( value1, value2,...v…

操作系统CLOCK算法

操作系统时钟(CLOCK)置换算法_时钟置换算法-CSDN博客 前七步相同 第八步的时候 发现页面在内存中 标记位变成1 但是指针不需要移动。

什么软件可以去视频水印?分享3个超实用去水印工具

什么软件可以去视频水印&#xff1f;短视频已然成为了我们日常生活或工作的一部分&#xff0c;当我们遇到感兴趣的视频想保存发现无法保存&#xff0c;或者保存后留有水印&#xff0c;非常影响我们视频观看度和分享欲&#xff0c;为了解决这一问题&#xff0c;许多针对视频水印…