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

news2024/9/28 7:23:05

在这里插入图片描述

个人简介: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工具:StrUtil
                  return true;
              }
              return !str.matches(regex);
          }
      }
      
      



  • 发送短信验证码 业务

    •     @Override
          public 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. 返回ok
              return Result.ok();
          }
      



  • 登录、注册 业务

    •     /**
           *   session实现登录功能
           * @param loginForm
           * @param session
           * @return
           */
          @Override
          public 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); //设置phone
                  user.setNickName(USER_NICK_NAME_PREFIX + RandomUtil.randomString(10)); //设置随机昵称
                  this.save(user); // 存入数据库(mybatisPlus提供的Service层方法)
              }
      
              //7. 用户存在,存入session域
              session.setAttribute("user", BeanUtil.copyProperties(user, UserDTO.class));
      
              //返回ok
              return 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 {
          
          @Override
          public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
              // 1.获取session
              HttpSession 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 {
      
          @Resource
          private StringRedisTemplate stringRedisTemplate;
      
          @Override
          public 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.coloradmin.cn/o/1262516.html

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

相关文章

「阿里巴巴」裁撤量子实验室!

据内部消息&#xff0c;阿里巴巴达摩院由于预算及盈利等原因&#xff0c;已经撤裁旗下量子实验室。此次&#xff0c;共计裁减30余人。 达摩院官网已撤下量子实验室的相关介绍页面。上图&#xff1a;早先关于量子实验室的相关介绍&#xff1b;下图&#xff1a;现在达摩院官网“实…

招标采购软件如何让采购变得更轻松?

企业总是希望让采购流程更简单&#xff0c;选择更好的供应商&#xff0c;花更少的钱。采购软件的普及使原材料和服务的采购变得更容易&#xff0c;向供应商&#xff08;甚至是全球供应商&#xff09;索取信息的流程已大大简化。包括招标采购软件在内的采购技术已成为企业运营不…

11.Spring源码解析-beans解析

很明显又调用回来了&#xff0c;是典型的递归调用

璞华大数据产品入选中国信通院“铸基计划”

武汉璞华大数据技术有限公司HawkEye设备数字化管理平台产品&#xff0c;凭借优秀的产品技术能力&#xff0c;通过评估后&#xff0c;入选中国信通院“铸基计划”《高质量数字化转型产品及服务全景图&#xff08;2023&#xff09;》的工业数字化领域。 “铸基计划”是中国信通院…

MySQL数据库入门到大牛_基础_17_触发器

文章目录 1. 触发器概述2. 触发器的创建2.1 创建触发器语法2.2 代码举例 3. 查看、删除触发器3.1 查看触发器3.2 删除触发器 4. 触发器的优缺点4.1 优点4.2 缺点4.3 注意点 5. 第十七章练习 在实际开发中&#xff0c;我们经常会遇到这样的情况&#xff1a;有 2 个或者多个相互关…

文章采集器-免费的文章采集工具大全

在当今信息爆炸的时代&#xff0c;获取有效的信息变得尤为关键。随之而来的问题是&#xff0c;如何高效地从海量信息中筛选出我们所需的内容呢&#xff1f;文章采集器应运而生&#xff0c;它就像是信息世界中的一把神奇的筛子&#xff0c;能够帮助我们从大海一般的信息中捞取我…

linux 内核线程

内核线程类似于用户进程&#xff0c;通常用于并发处理些工作&#xff0c;它是一种在内核空间实现后台任务的方式&#xff0c;并且可以参与时间片轮转调度。 内核线程可以进行繁忙的异步事件处理&#xff0c;也可以睡眠等待某事件的发生&#xff0c;内核线程可以访问内核函数和…

【hive-design】hive架构详解:描述了hive架构,hive主要组件的作用、hsql在hive执行过程中的底层细节、hive各组件作用

文章目录 一. Hive Architecture二. Metastore1. Metastore Architecture2. Metastore Interface 三. Compiler四. hive架构小结 本文主要讨论了 描述了hive架构&#xff0c;hive主要组件的作用详细描述了hsql在hive执行过程中的底层细节描述了hive各组件作用 一. Hive Archite…

Authing CEO 谢扬来信 |我的原则

从忙碌的工作中短暂抽身&#xff0c;有很多感想&#xff0c;不吐不快&#xff0c;借此机会&#xff0c;倾我所有&#xff0c;诉我原则。 原则一&#xff1a;坚强信念&#xff0c;坚定意志 商人大多「无利不起早」&#xff0c;而创业者的反馈周期比商人长非常非常多。 相比「商品…

微服务知识大杂烩

1.什么是微服务? 微服务(Microservices)是一种软件架构风格,将一个大型应用程序划分为一组小型、自治且松耦合的服务。每个微服务负责执行特定的业务功能,并通过轻量级通信机制(如HTTP)相互协作。每个微服务可以独立开发、部署和扩展,使得应用程序更加灵活、可伸缩和可…

认证授权常见方式

认证授权 认证 (Authentication) 和授权 (Authorization)的区别是什么&#xff1f; 说简单点就是&#xff1a; 认证 (Authentication)&#xff1a; 你是谁。授权 (Authorization)&#xff1a; 你有权限干什么。 稍微正式点&#xff08;啰嗦点&#xff09;的说法就是&#x…

15亿元!类ChatGPT平台AI21 Labs,获巨额融资

著名生成式AI平台AI21 Labs在官网宣布&#xff0c;获得2.08亿美元&#xff08;约15亿元&#xff09;C系列融资&#xff0c;估值14亿美元&#xff08;约100亿&#xff09;。 本次由英特尔旗下风投机构、康卡斯特旗下风投机构、现有投资者Ahren Innovation Capital等联合投资&am…

使用Zoho Projects项目管理系统进行研发排期的策略与方法

研发排期旨在有序地填充待开发的就绪队列&#xff0c;明确最近的发布计划&#xff0c;让准备就绪的需求如行云流水般进入开发阶段。 使用Zoho Projects项目管理系统进行研发排期的步骤如下&#xff1a; 1.创建项目&#xff1a; 登录Zoho Projects账户&#xff0c;创建一个新项…

java学习part19接口

113-面向对象(高级)-接口的使用_哔哩哔哩_bilibili 1.接口概念 个人认为是一种能力&#xff0c;某个类是否具有某种能力。一个类实现了一个接口就相当于学会了某些功能。 2.使用 接口里的属性都是全局常量public static final&#xff0c;即便不写也会自动加上。 3.多实现 4.接…

wsl 命令详解

WSL 简介 WSL全称 Windows Subsystem for Linux &#xff0c;是微软开发的一个运行在Windows上的兼容层&#xff0c;它允许开发人员和用户直接在Windows上运行原生Linux二进制文件&#xff0c;而无需配置或修改系统。 WSL命令是用于管理和操作WSL子系统的工具。 常用WSL命令…

【运维知识大神篇】超详细的ELFK日志分析教程5(Logstash中Filter常用插件详解+实战练习)

本篇文章主要讲解logstash的有关内容&#xff0c;包括filter的grok、date、user_agent、geoip、mutate插件&#xff0c;多个输入输出方案&#xff08;多实例if多分支语句&#xff09;&#xff0c;每个知识点都涉及实战练习&#xff0c;在实战中学习&#xff0c;事半功倍&#x…

信号分析仪-4024CA频谱分析仪 频率范围9kHz~9GHz

01 4024CA频谱分析仪 产品综述&#xff1a; 4024CA频谱分析仪是一款专为外场测试而设计的大宽带手持式实时频谱分析仪&#xff0c;最大实时分析带宽达到120MHz&#xff0c;具有实时频谱分析、5G NR解调分析、LTE FDD/TDD解调分析、GSM/EDGE解调分析、定向分析等多种测量功能…

英伟达“阉割版”AI芯片遇阻,推迟至明年发布 | 百能云芯

近日&#xff0c;英伟达&#xff08;Nvidia&#xff09;为遵守美国出口规定而推迟在中国市场推出的新款人工智能&#xff08;AI&#xff09;芯片引起了业界广泛关注。 据路透社报道&#xff0c;两位消息人士透露&#xff0c;该芯片被命名为H20&#xff0c;是英伟达为遵守美国最…

JavaEE(SpringMVC)期末复习(选择+填空+解答)

文章目录 JavaEE期末复习一、单选题&#xff1a;二、多选题三、填空题四、解答 JavaEE期末复习 一、单选题&#xff1a; 1.Spring的核⼼技术是&#xff08; A &#xff09;&#xff1f; A依赖注入 B.JdbcTmplate C.声明式事务 D.资源访问 Spring的核心技术包括依赖注入&#x…

从零带你底层实现unordered_map (2)

&#x1f4af; 博客内容&#xff1a;从零带你实现unordered_map &#x1f600; 作  者&#xff1a;陈大大陈 &#x1f680; 个人简介&#xff1a;一个正在努力学技术的准C后端工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎私信&#xff01; &#x1f496; 欢迎大家…