黑马点评短信登录功能

news2024/9/21 0:50:56

一、基于session实现短信登录

1、发送短信验证码

流程图如下:
在这里插入图片描述
1、实现UserController下的sendCode方法:

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

2、在userService下添加sendCode方法,根据流程图实现每一步的功能,校验手机号以及生成验证码的功能都是直接封装好的,在这里仅仅是利用后端模拟了发送验证码的功能:

    public Result sendCode(String phone, HttpSession session) {

        //1、校验手机号
        if(isPhoneInvalid(phone)){

            //2、手机号无效,返回错误信息
            return Result.fail("手机号无效!");
        }
        //3、手机号有效,生成验证码
        String code = RandomUtil.randomNumbers(6);
        //4、将验证码保存在session中
        session.setAttribute("code", code);
        //5、模拟发送验证码
        log.debug("发送验证码成功:验证码:{}", code);
        //返回ok
        return Result.ok();
    }
   

3、前端验证码获取成功
在这里插入图片描述

2、短信验证码登录注册

流程图如下:
在这里插入图片描述
1、实现UserController的下的login方法:

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

2、在UserService下添加login方法,同样根据流程图实现功能,在这里隐藏了用户的敏感信息,如密码等,仅在session中存入电话,头像以及昵称信息,通过BeanUtil.copyProperties()实现属性复制,将User对象转化为UserDto:

    public Result login(LoginFormDTO loginForm, HttpSession session) {
        //1、校验手机号
        String phone = loginForm.getPhone();
        if(isPhoneInvalid(phone)){
            //2、手机号无效,返回错误信息
            return Result.fail("手机号无效!");
        }
        //手机号有效
        //4、取出session中的验证码
        Object cacheCode = session.getAttribute("code");
        //5、取出登录时输入的验证码
        String loginCode = loginForm.getCode();
        //6、校验验证码,如果验证码过期或者未获取到,以及验证码不正确
        if(cacheCode == null || !cacheCode.toString().equals(loginCode)){
            //7、返回错误信息
            return Result.fail("验证码错误");
        }
        //8、查询用户是否存在
        User user = query().eq("phone", phone).one();
        //9、不存在,创建新用户
        if(user == null) {
            user = createUserWithPhone(phone);
        }
        //10、将用户信息存入session
        session.setAttribute("user", BeanUtil.copyProperties(user, UserDTO.class));//隐藏用户的敏感信息,仅返回用户手机号,id,头像
        return Result.ok();
    }

    private User createUserWithPhone(String phone) {
        User user  = new User();
        user.setPhone(phone);
        user.setNickName(USER_NICK_NAME_PREFIX + RandomUtil.randomString(10));
        //保存用户
        save(user);
        return user;
    }

3、校验登录状态

在第2步中,我们已经实现了短信验证码登录注册的功能,但是没有做登录校验。
在这里插入图片描述
上图中的请求是携带了 cookie 的,cookie 里是包含了 JSESSIONID 的。

服务端可以基于 JSESSIONID 来获得 session ,再从 session 里取出用户,进而来判断该用户是否存在。

但是这个流程里有一个问题,我们需要在每一个 controller 里来写这些业务逻辑。

在这里插入图片描述
我们可以通过拦截器(由 SpringMVC 提供)来统一拦截判断,最后决定是否放行。

此外,如果要做分布式 session,会存在系统负担和性能以及安全问题。考虑到系统负担和安全,我们可以在拦截器拦截到之后,将 session 中的用户信息保存到 ThreadLocal 中。每一个进入 Tomcat 的请求都是一个独立的线程,那么将来 ThreadLocal 就会在线程内开启一个独立的空间去保存这些请求(请求中携带了对应的用户信息)。这样一来,不同的用户访问 controller,都是一个独立的线程,每一个线程都有自己的用户信息,相互独立不干扰,controller 从 ThreadLocal 中取出用户信息。)

1、我们新建一个拦截器loginIntercepter

public class LoginInterceptor implements HandlerInterceptor {
    @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;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //7、移除用户
        UserHolder.removeUser();
    }
}

2、接下来我们配置这个拦截器,新建一个MvcConfig 实现 WebMvcConfigurer接口,将拦截器添加,并且排除掉不需要拦截的路径(发送短信验证码,短信验证码登录等):

@Configuration
public class MvcConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginInterceptor())
                .excludePathPatterns(
                        "/shop/**",
                        "/voucher/**",
                        "/shop-type/**",
                        "/upload/**",
                        "/blog/hot",
                        "/user/code",
                        "/user/login"
                );
    }
}

4、session共享问题的分析

在这里插入图片描述
所以如果在多台Tomcat的情况下,就会存在session的共享问题,在后续通过Redis来解决这个问题,Redis同样满足内存存储以及键值对的结构,最为重要的一点就是可以实现数据共享。

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

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

相关文章

微博粉丝清理工具丨2023年最新粉丝批量清理_微博怎么批量清理粉丝

2023年最新微博怎么批量清理粉丝?可能还有不少小伙伴不太清楚 接下来就为大家带来微博批量清理僵尸粉方法 有需要的朋友可以来了解一下,希望下文可以帮到大家 第一种:客服界面清粉方法 然后在客服中心界面选择修正粉丝; 最后点击一下确认就…

const修饰的成员函数

const修饰的成员函数 问题: 哪里出现编译报错了, 如何修改? class A { public:const int get1() const{a1 10;return a1;}private: int a1 0; }; int main() {A a;a.get1();return 0; }当时以为是a是一个非const对象,调用了const成员函数导致编译错误…

关于guacamole项目中的一点感悟与理解

关于guacamole项目中的一点想法 前言一、guacd模块启动相关二、一些感悟与理解参考 前言 Guacamole 是基于 Web 的 VNC 客户端,使用它可以通过web浏览器访问远程服务器终端并进行操作。它的基本架构如下图所示。 巧合之下,前段时间了解了项目中guacd模块…

构建大数据环境:Hadoop、MySQL、Hive、Scala和Spark的安装与配置

前言 在当今的数据驱动时代,构建一个强大的大数据环境对于企业和组织来说至关重要。本文将介绍如何安装和配置Hadoop、MySQL、Hive、Scala和Spark,以搭建一个完整的大数据环境。 简介 安装Hadoop 首先,从Apache Hadoop的官方网站下载所需的…

测试(一)

1.用户需求 可以简单理解为甲方提出的需求,如果没有甲方,那么就是终端用户使用产品时必须要完成的任务。该需求一般比较简略。 2.软件需求 或者叫功能需求,该需求会详细描述开发人员必须实现的软件功能(所谓的测试文档)。 大多数公司在进行…

05- c语言函数 (C语言)

一 函数的概念 1、在程序设计过程中,为了实现某个功能需要编写多行代码,例如求一个二维数组中的最大值,如果 该功能需要被多次使用,我们可以在每次使用时将原来的代码重复编写,但是这样未免有“凑代码”的嫌疑&#x…

大数据治理.数据储存技术

hive是基于Hadoop的一个数据仓库工具,用来进行数据提取、转化、加载,这是一种可以存储、查询和分析存储在Hadoop中的大规模数据的机制。hive数据仓库工具能将结构化的数据文件映射为一张数据库表,并提供SQL查询功能,能将SQL语句转…

Spark大数据处理学习笔记(3.8.3) Spark RDD典型案例-利用RDD实现分组排行榜

该文章主要为完成实训任务,详细实现过程及结果见【http://t.csdn.cn/Twpwe】 文章目录 一、任务目标二、准备工作2.1 在本地创建成绩文件2.2 将成绩文件上传到HDFS上指定目录 三、完成任务3.1 在Spark Shell里完成任务3.1.1 读取成绩文件得到RDD3.1.2 利用映射算子生…

Openfire身份认证绕过漏洞复现+利用(CVE-2023-32315)

0x01 产品简介 Openfire是免费的、开源的、基于可拓展通讯和表示协议(XMPP)、采用Java编程语言开发的实时协作服务器。Openfire安装和使用都非常简单,并利用Web进行管理。单台服务器甚至可支持上万并发用户。 0x02 漏洞概述 Openfire的管理控制台是一个基于 Web 的…

自然语言处理从入门到应用——动态词向量预训练:ELMo词向量

分类目录:《自然语言处理从入门到应用》总目录 在双向语言模型预训练完成后,模型的编码部分(包括输入表示层以及多层堆叠LSTM)便可以用来计算任意文本的动态词向量表示。最自然的做法是使用两个LSTM的最后一层隐含层输出作为词的动…

Qt项目网络聊天室设计

效果演示 网络聊天室 Qt网络聊天室服务端 网络聊天室程序 基于TCP的可靠连接(QTcpServer、QTcpSocket) 一个服务器,多个客户端 3. 服务器接收到某个客户端的请求以及发送信息,经服务器发给其它客户端 最终实现一个共享聊天内容的聊天室! …

大数据治理.数据采集/归集技术

第一部分 阿里巴巴DATAx DataX 是阿里开源的一个异构数据源离线同步工具,致力于实现包括关系型数据库(MySQL、Oracle等)、HDFS、Hive、ODPS、HBase、FTP等各种异构数据源之间稳定高效的数据同步功能。 DataX设计理念 DataX本身作为数据同步框架,将不同…

分布式系统消息通信技术:MOM与RPC

一、中间件 什么是中间件 中间件(Middleware)是处于操作系统和应用程序之间的软件,也有人认为它应该属于操作系统中的一部分。人们在使用中间件时,往往是一组中间件集成在一起,构成一个平台(包括开发平台…

springboot配置 spring.profiles.active spring.profiles.include @profile

springboot配置 spring.profiles.active spring.profiles.include profile spring.profiles.active spring.profiles.include profile的命名方式 以 application-开头, --横杠(减号)不能少 application-{这部分自定义}.propertiesapplication-{这部分自定义}.ymlapplicatio…

c++多态详解

前言: 对于面向对象语言来说,多态是面向对象的三大特性之一,简单一点来说多态就是多种形态,是不同对象接收到同一种消息产生的不同动作或者反应,听起来有点抽象,实际上就是完成一个任务让不同的对象来做产生…

合宙Air724UG Cat.1模块硬件设计指南--模拟语音通道

模拟语音通道 简介 模拟音频技术是由传感器采集得到的连续变化的值,根据其电压的幅度用来展示声音强弱。CAT.1内置3种音频输出模式,分别为扬声器(SPK)输出,耳机(HP)输出和听筒(RECEIVER)输出。 特性 SPK接口 SPK-、SPK。Speaker差分信号接口…

记压测环境数据表死锁导致接口长时间pending问题

背景 压测过程中测试小伙伴反映某个页面长时间loading无法打开,接下来我们排查一下,既然是压测环境,那么就需要排除服务器资源层面的因素,现在考验的就是在系统资源不足时系统的情况,那么我们就直接从代码层面开始排查…

PADS-LAYOUT菜单及工具说明

目录 1 材料清单输出 2 元件属性检查 3 材料清单制作 4 原理图生成PDF 4.1PDF文件生成 4.2PDF文件查阅 4.3PDF文件打印 5 PADS转Altium Designer 5 Altium Designer转PADS 5.1 直接导入法 5.2 软件生成法 6 PADS层定义 7 设计规则输出 7.1 PADS对象管理 7.2 PAD…

pandas---分箱(离散化处理)、绘图、交叉表和透视表

1. 分箱 分箱操作就是将连续型数据离散化。分箱操作分为等距分箱和等频分箱. 1.1 等宽分箱 pandas.cut(x, bins, rightTrue, labelsNone, retbinsFalse, precision3, include_lowestFalse, duplicatesraise, orderedTrue) x:要分箱的一维数组或者 Series。 bi…

分布式系统概念和设计——分布式共享内存

分布式系统概念和设计 分布式共享内存 分布式共享内存是在不共享物理内存的计算机之间实现数据的共享的一个抽象。 有一个底层运行的系统保证其透明性,但是进程还是根据内存的分布处理物理内存的分布式能力 DMS最关键点: 不需要关心数据的通信&#xff…