黑马点评项目01——短信登录以及登录校验的细节

news2025/6/3 8:22:43

在这里插入图片描述

1.短信登录

1.1 Session方式实现

在这里插入图片描述
前端点击发送验证码,后端生成验证码后,向session中存放键值对,键是"code",值是验证码;然后,后端生成sessionID以Cookie的方式发给前端,前端拿到后,以后每一次访问都会携带这个Cookie;此时,前端点击登录的时候,会带着这个cookie进入后端,后端拿到这个sessionID后就知道是哪一个请求端发过来的,找到对应的session 验证码,然后对比是否相同;注意,此时要验证手机号是不是原来那个手机号,黑马点评只是验证了它是否满足一个手机号规则,并没有验证是原来那个手机号;根据手机号查询用户,没查到,数据库新建用户信息,查到了,把"user": UserDTO对象(User对象的简化版,不保留敏感信息)放到session中,这是为登录校验准备的,因为有些功能只有登录的状态才可以实现,我们可以把它放到拦截器中实现,实现HandlerInterceptor接口的preHandle方法,具体如下:

@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.不存在
            response.setStatus(401);
            return false;
        }
        // 5.存在,保存信息到本地线程中
        UserHolder.saveUser((UserDTO) user);
        return true;
    }

也就说,一些功能,session中没有user就不会让你过来,有user,就把UserDTO对象存放在本地线程中,如何是实现的呢?

package com.hmdp.utils;


import com.hmdp.dto.UserDTO;
import com.hmdp.entity.User;

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

缺点:
在单台服务器上,Session 保存在服务器内存中,客户端通过 Cookie 携带 Session ID,服务器根据 Session ID 直接找到对应的会话数据。
但是在多台 服务器(集群)中(多台tomcat),用户的请求可能每次都被不同的服务器接收,这时如果 Session 没有共享,某台服务器找不到该用户的 Session,导致用户无法保持登录状态。
解决方案:
1、无状态认证方式
使用 Token(如 JWT)登录,服务器不保存 Session,完全无状态,天然适合分布式集群。(学到了再说)
2、redis实现
多台服务器连接同一个redis实例,就避免了这个问题。

1.2 Redis实现

先来看一下RedisTemplate与StringRedisTemplate的区别:

RedisTemplate 可以自定义<K,V>的序列化方式,StringRedisTemplate 默认使用String序列化方式(键和值必须都是String类型),一般来说,用RedisTemplate的时候要自定义序列化方式(默认的JDK序列化方式不好用),键都是String ,值都是Jackson,这样可以将对象放到值里面。加上这种配置:

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory){
        // 创建RedisTemplate对象
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        // 设置连接工厂
        template.setConnectionFactory(connectionFactory);
        // 创建JSON序列化工具
        GenericJackson2JsonRedisSerializer jsonRedisSerializer =
                new GenericJackson2JsonRedisSerializer();
        // 设置Key的序列化 string
        template.setKeySerializer(RedisSerializer.string());
        template.setHashKeySerializer(RedisSerializer.string());
        // 设置Value的序列化 json
        template.setValueSerializer(jsonRedisSerializer);
        template.setHashValueSerializer(jsonRedisSerializer);
        // 返回
        return template;
    }
}

配置好之后,可以直接这样使用:


// 存储对象
User user = new User("Alice", 20);
redisTemplate.opsForValue().set("user:1", user);

// 读取对象
User userFromRedis = (User) redisTemplate.opsForValue().get("user:1");
System.out.println(userFromRedis.getName());  // 输出:Alice

对于之前StringRedisTemplate的一点疑惑的解决:
在这里插入图片描述
它也可以操作Hash,Set,只不过是键和值都是String类型的,下面是一些示例

@Autowired
private StringRedisTemplate stringRedisTemplate;

// 操作 Hash
stringRedisTemplate.opsForHash().put("user:1000", "name", "Alice");
stringRedisTemplate.opsForHash().put("user:1000", "age", "18");

// 操作 Set
stringRedisTemplate.opsForSet().add("onlineUsers", "user1");
stringRedisTemplate.opsForSet().add("onlineUsers", "user2");

回归正题:这里我们使用RedisTemplate,因为我们要用到一次存放的值是对象
前端点击发送验证码,后端向redis存放键值对<phone,验证码>并设置3min有效期,都是String类型哈,前端点击登录时,redis有没有这样一个键值对,返回是一个对象,如果不是空,要toString(),然后再equals(),如果比对成功,根据手机号,在数据库查询是否有这么个用户,没有就创建,然后把对象存放到redis中,那么问题来了,键应该是什么,我们这里随机生成全局唯一token, UUID.randomUUID()作为标识符key;在登录校验中,我们需要获取请求头中的token, String token = request.getHeader("authorization");根据这个token在redis查询比对,实现拦截功能。
注意与JWT+Token的区别

在这里插入图片描述

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

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

相关文章

【笔记】Windows 系统安装 Scoop 包管理工具

#工作记录 一、问题背景 在进行开源项目 Suna 部署过程中&#xff0c;执行设置向导时遭遇报错&#xff1a;❌ Supabase CLI is not installed. 根据资料检索&#xff0c;需通过 Windows 包管理工具Scoop安装 Supabase CLI。 初始尝试以管理员身份运行 PowerShell 安装 Scoop…

MySQL之约束和表的增删查改

MySQL之约束和表的增删查改 一.数据库约束1.1数据库约束的概念1.2NOT NULL 非空约束1.3DEFAULT 默认约束1.4唯一约束1.5主键约束和自增约束1.6自增约束1.7外键约束1.8CHECK约束 二.表的增删查改2.1Create创建2.2Retrieve读取2.3Update更新2.4Delete删除和Truncate截断 一.数据库…

Oracle数据库性能优化的最佳实践

原创&#xff1a;厦门微思网络 以下是 Oracle 数据库性能优化的最佳实践&#xff0c;涵盖设计、SQL 优化、索引管理、系统配置等关键维度&#xff0c;帮助提升数据库响应速度和稳定性&#xff1a; 一、SQL 语句优化 1. 避免全表扫描&#xff08;Full Table Scan&#xff09;…

汽配快车道:助力汽车零部件行业的产业重构与数字化出海

汽配快车道&#xff1a;助力汽车零部件行业的数字化升级与出海解决方案。 在当今快速发展的汽车零部件市场中&#xff0c;随着消费者对汽车性能、安全和舒适性的要求不断提高&#xff0c;汽车刹车助力系统作为汽车安全的关键部件之一&#xff0c;其市场需求也在持续增长。汽车…

Windows 11 家庭版 安装Docker教程

Windows 家庭版需要通过脚本手动安装 Hyper-V 一、前置检查 1、查看系统 快捷键【winR】&#xff0c;输入“control” 【控制面板】—>【系统和安全】—>【系统】 2、确认虚拟化 【任务管理器】—【性能】 二、安装Hyper-V 1、创建并运行安装脚本 在桌面新建一个 .…

PyQt6基础_QtCharts绘制横向柱状图

前置&#xff1a; pip install PyQt6-Charts 结果&#xff1a; 代码&#xff1a; import sysfrom PyQt6.QtCharts import (QBarCategoryAxis, QBarSet, QChart,QChartView, QValueAxis,QHorizontalBarSeries) from PyQt6.QtCore import Qt,QSize from PyQt6.QtGui import QP…

《TCP/IP 详解 卷1:协议》第2章:Internet 地址结构

基本的IP地址结构 分类寻址 早期Internet采用分类地址&#xff08;Classful Addressing&#xff09;&#xff0c;将IPv4地址划分为五类&#xff1a; A类和B类网络号通常浪费太多主机号&#xff0c;而C类网络号不能为很多站点提供足够的主机号。 子网寻址 子网&#xff08;Su…

如何通过一次需求评审,让项目效率提升50%?

想象一下&#xff0c;你的团队启动了一个新项目&#xff0c;但需求模糊不清&#xff0c;开发到一半才发现方向错了&#xff0c;返工、加班、客户投诉接踵而至……听起来像噩梦&#xff1f;一次完美的需求评审就能避免这一切&#xff01;它就像项目的“导航仪”&#xff0c;确保…

再见Notepad++,你好Notepad--

Notepad-- 是一款国产开源的轻量级、跨平台文本编辑器&#xff0c;支持 Window、Linux、macOS 以及国产 UOS、麒麟等操作系统。 除了具有常用编辑器的功能之外&#xff0c;Notepad-- 还内置了专业级的代码对比功能&#xff0c;支持文件、文件夹、二进制文件的比对&#xff0c;支…

element-plus bug整理

1.el-table嵌入el-image标签预览时&#xff0c;显示错乱 解决&#xff1a;添加preview-teleported属性 <el-table-column label"等级图标" align"center" prop"icon" min-width"80"><template #default"scope"&g…

技术-工程-管用养修保-智能硬件-智能软件五维黄金序位模型

融智学工程技术体系&#xff1a;五维协同架构 基于邹晓辉教授的框架&#xff0c;工程技术体系重构为&#xff1a;技术-工程-管用养修保-智能硬件-智能软件五维黄金序位模型&#xff1a; math \mathbb{E}_{\text{技}} \underbrace{\prod_{\text{Dis}} \text{TechnoCore}}_{\…

LangChain-自定义Tool和Agent结合DeepSeek应用实例

除了调用LangChain内置工具外&#xff0c;也可以自定义工具 实例1&#xff1a; 自定义多个工具 from langchain.agents import initialize_agent, AgentType from langchain_community.agent_toolkits.load_tools import load_tools from langchain_core.tools import tool, …

用 3D 可视化颠覆你的 JSON 数据体验

大家好&#xff0c;这里是架构资源栈&#xff01;点击上方关注&#xff0c;添加“星标”&#xff0c;一起学习大厂前沿架构&#xff01; 复杂的 JSON 数据结构常常让人头疼&#xff1a;层层嵌套的对象、错综复杂的数组关系&#xff0c;用传统的树状视图或表格一览千头万绪&…

MVCC(多版本并发控制)机制

1. MVCC&#xff08;多版本并发控制&#xff09;机制 MVCC 的核心就是 Undo Log Read View&#xff0c;“MV”就是通过 Undo Log 来保存数据的历史版本&#xff0c;实现多版本的管理&#xff0c;“CC”是通过 Read View 来实现管理&#xff0c;通过 Read View 原则来决定数据是…

Mac M1 安装 ffmpeg

1.前言 官网那货没有准备m系列的静态包&#xff0c;然后我呢&#xff0c;不知道怎么想的就从maven项目中的 javacv-platform&#xff0c;且版本为1.5.11依赖里面将这个静态包把了出来&#xff0c;亲测能用&#xff0c;感觉比那些网上说的用什么wget编译安装、brew安装快多了。…

Spring框架学习day3--Spring数据访问层管理(IOC)

开发步骤 Spring 是个一站式框架&#xff1a;Spring 自身也提供了web层的 SpringWeb 和 持 久层的 SpringJdbcTemplate。 开发步骤 1.导入jar包 pom.xml <!-- spring-jdbc--> <dependency><groupId>org.springframework</groupId><artifactId>…

重读《人件》Peopleware -(13)Ⅱ 办公环境 Ⅵ 电话

当你开始收集有关工作时间质量的数据时&#xff0c;你的注意力自然会集中在主要的干扰源之一——打进来的电话。一天内接15个电话并不罕见。虽然这看似平常&#xff0c;但由于重新沉浸所需的时间&#xff0c;它可能会耗尽你几乎一整天的时间。当一天结束时&#xff0c;你会纳闷…

Python训练营打卡Day40

DAY 40 训练和测试的规范写法 知识点回顾&#xff1a; 1.彩色和灰度图片测试和训练的规范写法&#xff1a;封装在函数中 2.展平操作&#xff1a;除第一个维度batchsize外全部展平 3.dropout操作&#xff1a;训练阶段随机丢弃神经元&#xff0c;测试阶段eval模式关闭dropout 作…

制作一款打飞机游戏63:自动保存

1.编辑器的自动保存实现 ‌目标‌&#xff1a;将自动保存功能扩展到所有编辑器&#xff0c;包括脑编辑器、模式编辑器、敌人编辑器和动画/精灵编辑器。‌实现方式‌&#xff1a; ‌代码复制‌&#xff1a;将关卡编辑器中的自动保存代码复制到其他编辑器中。‌标记数据变更‌&a…

golang连接sm3认证加密(app)

文章目录 环境文档用途详细信息 环境 系统平台&#xff1a;Linux x86-64 Red Hat Enterprise Linux 7 版本&#xff1a;4.5 文档用途 golang连接安全版sm3认证加密数据库,驱动程序详见附件。 详细信息 1.下载Linux golang安装包 go1.17.3.linux-amd64.tar.gz 1.1. 解压安…