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

embedded/2024/10/22 16:42:38/

目录

基于Session的短信登录

 ①首先看他的业务逻辑

②进行代码逻辑处理

基于Redis的短信登录

 ①首先看他的业务逻辑

 ②进行代码逻辑处理

 Controller:

 Service接口:

  Service实例:

 Mapper:

  封装ThreadLocal线程的数据操作:

 自定义拦截器:

 拦截器配置文件:

 Redis常量配置文件:

 正则表达式文件:


基于Session的短信登录

 ①首先看他的业务逻辑

②进行代码逻辑处理

Controller层:

java">@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层:

java">@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:
java">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接口:
java">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实例:
java">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:
java">import com.hmdp.entity.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;public interface UserMapper extends BaseMapper<User> {}
  封装ThreadLocal线程的数据操作:
java">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();}
}
 自定义拦截器:
java">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();}
}
 拦截器配置文件:
java">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常量配置文件:
java">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;
}
 正则表达式文件:
java">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.ppmy.cn/embedded/30628.html

相关文章

最全 CSS 学习指南

文章导读&#xff1a;AI 辅助学习前端&#xff0c;包含入门、进阶、高级部分前端系列内容&#xff0c;当前是 CSS 的部分&#xff0c;瑶琴会持续更新&#xff0c;适合零基础的朋友&#xff0c;已有前端工作经验的可以不看&#xff0c;也可以当作基础知识回顾。 在上篇文章中&a…

最小K个数(力扣面试题17.14)

本文采用的是大堆排序求最小的K个值。需要有堆的数据结构基础哦。 代码展示&#xff1a; /*** Note: The returned array must be malloced, assume caller calls free().*/ void AdjustDown(int* parr,int n,int root)//向下调整 {int parentroot;int child parent*21;while…

k8s笔记 | Ingress

安装Ingress 添加helm创库 Installation Guide - Ingress-Nginx Controller Ingress | Kubernetes 下载包 将 文件helm 放到 /usr/local/bin/ 并给到执行权限 # 添加可执行权限 chmod ux helm # 测试是否能运行 helm version# 结果 version.BuildInfo{Version:"v3.14…

uniapp 监听APP切换前台、后台插件 Ba-Lifecycle

监听APP切换前台、后台 Ba-Lifecycle 简介&#xff08;下载地址&#xff09; Ba-Lifecycle 是一款uniapp监听APP切换前台、后台的插件&#xff0c;简单易用。 截图展示 也可关注博客&#xff0c;实时更新最新插件&#xff1a; uniapp 常用原生插件大全 使用方法 在 script…

NLP自然语言处理和应用场景介绍

【A】NLP&#xff08;Natural Language Processing&#xff0c;自然语言处理&#xff09;是计算机科学与人工智能领域的一个分支&#xff0c;旨在让机器能够理解、解释、生成人类语言。它涵盖了语言文本的语法、语义、语用、语境等方面的处理。 NLP的具体应用场景包括但不限于…

华为云耀云服务器开放端口

博客主页&#xff1a;花果山~程序猿-CSDN博客 关注我一起学习&#xff0c;一起进步&#xff0c;一起探索编程的无限可能吧&#xff01;让我们一起努力&#xff0c;一起成长&#xff01; 目录 一.华为云控制台开放端口 寻找到安全组信息 2. 添加开放的端口信息 3. 检查是否成…

基于深度学习检测恶意流量识别框架(80+特征/99%识别率)

基于深度学习检测恶意流量识别框架 目录 基于深度学习检测恶意流量识别框架简要示例a.检测攻击类别b.模型训练结果输出参数c.前端检测页面d.前端训练界面e.前端审计界面&#xff08;后续更新了&#xff09;f.前端自学习界面&#xff08;自学习模式转换&#xff09;f1.自学习模式…

Java的逻辑控制和方法的使用介绍

前言 程序的逻辑结构一共有三种&#xff1a;顺序结构、分支结构和循环结构。顺序结构就是按代码的顺序来执行相应的指令。这里主要讲述Java的分支结构和循环结构&#xff0c;由于和C语言是有相似性的&#xff0c;所以这里只会提及不同点和注意要点~~ 注意在C语言中&#xff0c;…