Redis---------实现短信登录业务

目录

基于Session的短信登录

 ①首先看他的业务逻辑

②进行代码逻辑处理

基于Redis的短信登录

 ①首先看他的业务逻辑

 ②进行代码逻辑处理

 Controller:

 Service接口:

  Service实例:

 Mapper:

  封装ThreadLocal线程的数据操作:

 自定义拦截器:

 拦截器配置文件:

 Redis常量配置文件:

 正则表达式文件:


基于Session的短信登录

 ①首先看他的业务逻辑

②进行代码逻辑处理

Controller层:

@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {@Resourceprivate IUserService userService;@Resourceprivate IUserInfoService userInfoService;/*** 发送手机验证码*/@PostMapping("code")public Result sendCode(@RequestParam("phone") String phone, HttpSession session) {return userService.sendCode(phone,session);}/*** 登录功能* @param loginForm 登录参数,包含手机号、验证码;或者手机号、密码*/@PostMapping("/login")public Result login(@RequestBody LoginFormDTO loginForm, HttpSession session){return userService.login(loginForm,session);}//跳转到我的页面@GetMapping("/me")public Result me(){User user = UserHolder.getUser();return Result.ok(user);}

 Service层:

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {//发送验证码@Overridepublic Result sendCode(String phone, HttpSession session) {//1,校验手机号,看手机号是否合规if (RegexUtils.isPhoneInvalid(phone)) {//2,不符合则返回错误结果return Result.fail("手机号错误!");}//3,符合就生成验证码String code = RandomUtil.randomNumbers(6);//4,保存验证码在Session中session.setAttribute("code",code);//5,发送验证码给前端log.debug("发送验证码: "+code);return Result.ok();}//登陆@Overridepublic Result login(LoginFormDTO loginForm, HttpSession session) {//1,校验手机号,看手机号是否合规String phone = loginForm.getPhone();if (RegexUtils.isPhoneInvalid(phone)) {//2,不符合则返回错误结果return Result.fail("手机号错误!");}//2,校验验证码Object Cachecode = session.getAttribute("code");//session里的验证码String code = loginForm.getCode();//前端提交过来的验证码if(Cachecode == null || !Cachecode.toString().equals(code)){//3,如果错误则返回return Result.fail("验证码错误!");}//4,正确的话就查询数据库中的数据User user = query().eq("phone", phone).one();//5,判断是否存在if(user == null){//6,如果没有查到就进行注册操作user= new User();user.setPhone(phone);user.setNickName( USER_NICK_NAME_PREFIX +RandomUtil.randomString(10));save(user);}//7,保存到Session中session.setAttribute("user",user);return Result.ok();}
}

 

基于Redis的短信登录

 ①首先看他的业务逻辑

 ②进行代码逻辑处理

 Controller:
import com.hmdp.dto.LoginFormDTO;
import com.hmdp.dto.Result;
import com.hmdp.entity.User;
import com.hmdp.entity.UserInfo;
import com.hmdp.service.IUserInfoService;
import com.hmdp.service.IUserService;
import com.hmdp.utils.UserHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpSession;@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {@Resourceprivate IUserService userService;@Resourceprivate IUserInfoService userInfoService;/*** 发送手机验证码,接受手机号参数以及session*/@PostMapping("code")public Result sendCode(@RequestParam("phone") String phone, HttpSession session) {//把参数传到Service层去实现业务功能return userService.sendCode(phone,session);}/*** login登录功能* @param loginForm 登录参数,包含手机号、验证码;或者手机号、密码以及session*/@PostMapping("/login")public Result login(@RequestBody LoginFormDTO loginForm, HttpSession session){把参数传到Service层去实现业务功能return userService.login(loginForm,session);}//进入我的页面发送的请求@GetMapping("/me")public Result me(){//在线程ThreadLocal把用户的数据拿出来并且返回到前端User user = UserHolder.getUser();System.out.println("user = " + user);//return Result.ok(user);}}
 Service接口:
import com.baomidou.mybatisplus.extension.service.IService;
import com.hmdp.dto.LoginFormDTO;
import com.hmdp.dto.Result;
import com.hmdp.entity.User;import javax.servlet.http.HttpSession;public interface IUserService extends IService<User> {Result sendCode(String phone, HttpSession session);Result login(LoginFormDTO loginForm, HttpSession session);
}
  Service实例:
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmdp.dto.LoginFormDTO;
import com.hmdp.dto.Result;
import com.hmdp.entity.User;
import com.hmdp.mapper.UserMapper;
import com.hmdp.service.IUserService;
import com.hmdp.utils.RegexUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpSession;
import java.util.concurrent.TimeUnit;
import static com.hmdp.utils.RedisConstants.*;
import static com.hmdp.utils.SystemConstants.USER_NICK_NAME_PREFIX;@Service
//extends ServiceImpl<UserMapper, User>是mybatisplus中的IService接口,可以实现CRUD的快速操作
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {@Autowired//redis-java客户端private StringRedisTemplate stringRedisTemplate;//发送验证码@Overridepublic Result sendCode(String phone, HttpSession session) {//1,校验手机号,看手机号是否合规if (RegexUtils.isPhoneInvalid(phone)) {//2,不符合则返回错误结果return Result.fail("手机号错误!");}//3,符合就生成验证码String code = RandomUtil.randomNumbers(6);//4,保存验证码在Redis,设置有效期两分钟stringRedisTemplate.opsForValue().set(LOGIN_CODE_KEY + phone, code , LOGIN_CODE_TTL , TimeUnit.MINUTES);//5,发送验证码给前端log.debug("发送验证码: "+code);return Result.ok();}//登录@Overridepublic Result login(LoginFormDTO loginForm, HttpSession session) {//1,校验手机号,看手机号是否合规String phone = loginForm.getPhone();if (RegexUtils.isPhoneInvalid(phone)) {//2,不符合则返回错误结果return Result.fail("手机号错误!");}//2,校验验证码String Cachecode = stringRedisTemplate.opsForValue().get(LOGIN_CODE_KEY + phone);//redis里的验证码String code = loginForm.getCode();//前端提交过来的验证码//redis里查不出数据,代表已经过期if(Cachecode == null || !Cachecode.equals(code)){//3,如果错误则返回return Result.fail("验证码错误!");}//4,正确的话就查询数据库中的数据User user = query().eq("phone", phone).one();//5,判断是否存在if(user == null){//6,如果没有查到就进行注册操作user= new User();user.setPhone(phone);user.setNickName( USER_NICK_NAME_PREFIX +RandomUtil.randomString(10));save(user);}//7,把用户数据保存到Redis中String token = IdUtil.randomUUID();//生成tokenString object_json = JSONUtil.parse(user).toString();//序列化stringRedisTemplate.opsForValue().set(LOGIN_USER_KEY+token,object_json,LOGIN_USER_TTL,TimeUnit.MINUTES);return Result.ok(token);}}
 Mapper:
import com.hmdp.entity.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;public interface UserMapper extends BaseMapper<User> {}
  封装ThreadLocal线程的数据操作:
import com.hmdp.entity.User;//线程里的数据的封装操作
public class UserHolder {private static final ThreadLocal<User> 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();}
}
 自定义拦截器:
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.hmdp.entity.User;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import java.util.concurrent.TimeUnit;import static com.hmdp.utils.RedisConstants.LOGIN_USER_KEY;public class LoginInterceptor implements HandlerInterceptor {private StringRedisTemplate stringRedisTemplate;public LoginInterceptor(StringRedisTemplate stringRedisTemplate) {this.stringRedisTemplate = stringRedisTemplate;}@Override//前置拦截器public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//校验登录状态//1,获取TokenString token = request.getHeader("authorization");if (StrUtil.isBlank(token)) {response.setStatus(401);return false;}//2,获取Redis中的用户String s = stringRedisTemplate.opsForValue().get(LOGIN_USER_KEY+token);User user= JSONUtil.toBean(s, User.class);//3,判断用户是否存在if (user == null){//4,不存在直接拦截response.setStatus(401);return false;}//4,存在则保存信息到ThreadLocalUserHolder.saveUser(user);//5,刷新Token的有效期stringRedisTemplate.expire(LOGIN_USER_KEY+token,RedisConstants.LOGIN_USER_TTL, TimeUnit.MINUTES);return true;}@Override//后置拦截器public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {UserHolder.removeUser();}
}
 拦截器配置文件:
import com.hmdp.utils.LoginInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class MVCCONFIG implements WebMvcConfigurer {@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new LoginInterceptor(stringRedisTemplate))//“”里是添加要拦截的路径.addPathPatterns("/**")//“”里是设置不拦截的路径.excludePathPatterns("/user/login","/user/code","blog/hot","/shop/**","./shoptype/**","/upload/**","/voucher/**");}
}
 Redis常量配置文件:
public class RedisConstants {public static final String LOGIN_CODE_KEY = "login:code:";public static final Long LOGIN_CODE_TTL = 2L;public static final String LOGIN_USER_KEY = "login:token:";public static final Long LOGIN_USER_TTL = 30L;
}
 正则表达式文件:
import cn.hutool.core.util.StrUtil;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);}}

在这里做一个总结:做这种业务主要是要捋清楚处理的步骤以及逻辑,像我们的发送验证码过程--->①前端发来数据请求参数和session②首先判断手机号是否符合正确的格式③如果不符合则返回错误,符合就可以生成验证码④验证码生成后将其保存到Redis中,并设置有效期⑤然后把验证码发送给前端。         前端收到验证码后填入并且点击登录按钮,就会发起一个带着参数的新的请求登录--->①后端收到请求首先判断手机号是否符合正确的格式②然后从Redis中把保存的验证码取出来与前端发过来的参数验证码进行比较③如果不相等或者Redis中无数据(即验证码已经过期)则返回错误④如果相等则去查询mysql数据库中是否有该数据⑤如果没有的话就要进行注册操作,把数据存到数据库中⑥最后把该数据存在Redis中并设置有限期。     点击登录后就会进入我们正式的”我的“页面。

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

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

相关文章

LeetCode 102.对称二叉树

题目描述 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 示例 1&#xff1a; 输入&#xff1a;root [1,2,2,3,4,4,3] 输出&#xff1a;true示例 2&#xff1a; 输入&#xff1a;root [1,2,2,null,3,null,3] 输出&#xff1a;false提示&#xff1a; 树中节点数…

手把手实现一个简约酷美美的版权声明模块

1. 导语 版权声明在很多网站都有用到&#xff0c;出场率还是很高的。所以今天就实现一个属于自己分风格的版权声明模块&#xff0c;技术上采用原生的前端三剑客: HTMLCSSJavaScript(可能会用到) 比如CSDN的版权声明是这样的 2. 需求分析 先看看成品吧&#xff0c;这篇文字结…

帕鲁杯2024 RE wp

1. Auth_System 改标志位ZF 2. 茶 壳脱不脱也没啥影响 查一下字符串&#xff0c;有个hint 那就猜测chacha20&#xff08;根本没想到&#xff09; ChaCha20 - Crypto Wikihttps://www.cryptopp.com/wiki/ChaCha20 法一&#xff1a;脚本解密 加密需要两个参数&#xff0c;ke…

最新即时聊天源码,支持视频语音聊天

最新即时聊天源码&#xff0c;支持视频语音聊天 网站手机电脑H5可打包APP、视频语音聊天、注册、添加好友、群聊创建、群管理、文件在线预览、群公告、后台管理 功能说明&#xff1a; 支持单聊和群聊&#xff0c;支持发送表情、图片、语音、视频和文件消息 单聊支持消息已读未…

java8 Stream流常用方法(持续更新中...)

java8 Stream流常用方法 1.过滤数据中年龄大于等于十八的学生2.获取对象中其中的一个字段并添加到集合(以学生姓名&#xff08;name&#xff09;为例)3.获取对象中其中的一个字段并转为其他数据类型最后添加到集合(以学生性别&#xff08;sex&#xff09;为例&#xff0c;将Str…

国产操作系统上如何比较软件版本 _ 统信UOS _ 麒麟KOS _ 中科方德

原文链接&#xff1a;国产操作系统上如何比较软件版本 | 统信UOS | 麒麟KOS | 中科方德 Hello&#xff0c;大家好啊&#xff01;在国产操作系统上管理软件版本是确保系统安全性和功能稳定性的关键一环。今天&#xff0c;我将向大家展示如何通过编写脚本在国产操作系统上检查软件…

【前端】-【防止接口重复请求】

文章目录 需求实现方案方案一方案二方案三 需求 对整个的项目都做一下接口防止重复请求的处理 实现方案 方案一 思路&#xff1a;通过使用axios拦截器&#xff0c;在请求拦截器中开启全屏Loading&#xff0c;然后在响应拦截器中将Loading关闭。 代码&#xff1a; 问题&…

C# Winform父窗体打开新的子窗体前,关闭其他子窗体

随着Winform项目越来越多&#xff0c;界面上显示的窗体越来越多&#xff0c;窗体管理变得更加繁琐。有时候我们要打开新窗体&#xff0c;然后关闭多余的其他窗体&#xff0c;这个时候如果一个一个去关闭就会变得很麻烦&#xff0c;而且可能还会出现遗漏的情况。这篇文章介绍了三…

记一次生产事故的排查和解决

一. 事故概述 春节期间, 生产系统多次出现假死不可用现象, 导致绝大部分业务无法进行. 主要表现现象为接口无法访问. 背景为900W客户表和近实时ES, 以及春节期间疫情导致的普通卖菜场景近似秒杀等. 二. 排查过程 优先排查了info, error, catalina日志, 发现以下异常: 主要的…

C语言——单链表实现数据增删查改

一.前言 嗨嗨嗨&#xff0c;我们又见面了。前面我们已经学习了关于数据结构中的顺序表&#xff0c;今天我们来学习数据结构中的单链表。废话不多说让我们直接开始吧。 二.正文 1.1链表的概念 链表是一种物理存储结构上非连续、非顺序的存储结构&#xff0c;数据元素的逻辑顺…

【Flask开发实战】HTML模板代码复用之extends使用

一、前言 在 HTML 开发中&#xff0c;尤其是在使用模板引擎&#xff08;如 Jinja2&#xff0c;常用于 Flask 应用&#xff09;时&#xff0c;extends 是一个非常有用的指令&#xff0c;它用于实现模板继承&#xff0c;从而达到代码复用的目的。这可以让你定义一个基本模板&…

三体中的二向箔

目录 描述 外观 基本原理 攻击范围及影响 副作用 保存方式 实战情况 二向箔是在中国科幻名匠刘慈欣的作品《三体3&#xff1a;死神永生》中登场的宇宙规律武器之一。首次出现于一艘来自歌者“母世界”的宇宙飞船。由于宇宙战争愈演愈烈&#xff0c;二向箔对于高等文明而…