短信验证

一、基于Session

1、登录流程

1)发送验证码

用户在提交手机号后,会校验手机号是否合法,如果不合法,则要求用户重新输入手机号

如果手机号合法,后台此时生成对应的验证码,同时将验证码进行保存,然后再通过短信的方式将验证码发送给用户

2)短信验证码登录、注册

用户将验证码和手机号进行输入,
后台从session中拿到当前验证码,然后和用户输入的验证码进行校验,
如果不一致,则无法通过校验,
如果一致,则后台根据手机号查询用户,
如果用户不存在,则为用户创建账号信息,保存到数据库。
无论是否存在,都会将用户信息保存到session中,方便后续获得当前登录信息

2、实现验证码发送

使用MyBatisX实现项目的初始化

1)正则表达式

分别对手机号、密码、验证码进行校验

正则表达式可以去网上找

public class RegexPatterns {
/**
* 手机号正则
*/
public static final String PHONE_REGEX="1\\d{10}";
/**
* 邮箱正则
*/
public static final String EMAIL_REGEX="/^([a-z0-9_\\.-]+)@([\\da-z\\.-]+)\\.([a-z\\.]{2,6})$/";
/**
* 验证码正则
*/
public static final String VERIFY_CODE_REGEX="^[a-zA-Z\\d]{6}$"; }

2)正则校验工具类

controller传入的手机号进行校验

满足手机号正则表达式,手机号11位,并且只能为数字,才能校验通过

官网:https://doc.hutool.cn/pages/index/#简介

public class RegexUtils {

    /**
* 校验手机号是否合法
* @param phone
* @return
*/
public static boolean isPhoneInvalid(String phone){
boolean matches = phone.matches(RegexPatterns.PHONE_REGEX);
return matches;
} /**
* 校验验证码是否合法
* @param code
* @return
*/
public boolean isCodeInvalid(String code){
boolean matches = code.matches(RegexPatterns.VERIFY_CODE_REGEX);
return matches;
}
}

3)Controller层

@GetMapping("/code")
public boolean SendCode(String phone, HttpSession session){
boolean b = userService.sendCode(phone, session);
return b;
}

4)service层

首先对传入的手机号放到正则校验工具类中校验

校验成功后生成验证码

将验证码存入session中

将验证码在控制台以debug形式输出

@Resource
private UserService userService; public boolean sendCode(String phone, HttpSession session) {
//1、校验手机号是否合法
if (!RegexUtils.isPhoneInvalid(phone)) {
return false;
}
//2、生成随机验证吗
String code = RandomUtil.randomNumbers(6);
//3、保存验证码
session.setAttribute("code",code);
//4、打印日志
log.debug("发送短信验证码成功,验证码:{}",code);
return true;
}

注意:这里需要开启debug日志

controller层中加入@Slf4j注解

logging:
level:
com.example: debug
# 开启debug日志

结果:

3、实现验证码登录注册

短信验证登录注册逻辑:

  • 校验手机号
  • 校验验证码
    • 取出session中保存的验证码与表单中的输入的验证码吗进行比较
  • 不一致:报错
  • 一致:根据手机号查询用户
  • 判断用户是否存在
  • 不存在,根据手机号创建新用户并保存
    • 用户是凭空创建的,所以密码可以没有,
    • 用户呢称和头像都是随机默认的
  • 保存用户信息到session中
 
 

1)Controller层

我们登录需要获取两个参数
用户名和手机号,根据手机号来创建用户名

@PostMapping("/login")
public boolean login(LoginFormDTO loginFormDTO, HttpSession session){
boolean login = userService.Login(loginFormDTO, session);
return login;
}

为了使代码更加美观,创建一个参数封装类

/**
* 用户登录请求参数封装类
*/
@Data
public class LoginFormDTO {
private String code;
private String phone;
}

2)service层

/**
* 用户登录
* @param loginFormDTO
* @param session
* @return
*/
@Override
public boolean Login(LoginFormDTO loginFormDTO, HttpSession session) {
//1、首先校验手机号和验证码是否合法
String phone = loginFormDTO.getPhone();
if(!RegexUtils.isPhoneInvalid(phone)){
return false;
}
//2、校验验证码
Object cachecode = session.getAttribute("code");
String dtoCode = loginFormDTO.getCode();
if (dtoCode==null&&!dtoCode.equals(cachecode)) {
return false;
}
//3、根据手机号查询用户信息
QueryWrapper<User> queryWrapper=new QueryWrapper<User>();
queryWrapper.eq("phone", phone);
//4、根据查询条件查询数据库中满足以上条件的用户
User user = userMapper.selectOne(queryWrapper);
if (user==null) {
//创建用户
user=CreateUser(phone);
}
//5、保存用户信息到session中
session.setAttribute("user",user);
return true;
}

将创建用户的这段代码单独封装为一个函数

/**
* 创建用户
* @param phone
* @return
*/
private User CreateUser(String phone){
User user = new User();
user.setPhone(phone);
user.setNickName(RandomUtil.randomString(10));
//保存用户
save(user);
return user;
}

发送验证码

get http://localhost:8080/api/user/code?phone=13177576913

校验验证码并登录

post http://localhost:8080/api/user/login?phone=13177576913
&code=686422

结果:

4、优化一:全局通用返回对象

前面我的测试前端返回的数据都太过单调,因为这是一个功能的实现,并不是做一个完整的项目,但这样看起来确实不太美观
所以这里使用==全局统一API响应框架==对整个接口进行统一的异常处理封装,这样就不需要写那么多的异常处理类了。

1)引入依赖

使用rest-api-spring-boot-starter这个依赖,不用打开Redis,但这个依赖需要加上

<!--RestfulAPI-->
<dependency>
<groupId>cn.soboys</groupId>
<artifactId>rest-api-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2)注解

启动类上加上这个注解
@EnableRestFullApi
就只需要这两步
LOG日志都不一样了

注意:
这里的端口号是8000,也就是说使用这个依赖必须要8000端口,我们在配置文件中所
设置的web端口没有用了,无法自定义端口
运行

我们先进行用户脱敏

3)用户信息脱敏

将返回对象单独封装

@Data
public class UserDTO {
private Long id;
private String nickName;
private String icon;
}

修改登录login方法中的

/**
* copyProperties:属性拷贝——把user中的属性字动拷贝到UserDTO中
* BeanUtils:使用的是包cn.hutool.core.bean下的工具类
*/
//5、保存用户信息到session中
UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.class);
session.setAttribute("user", userDTO);

结果这里就不说了,成功返回三个信息

基于 Session 实现短信登录的更多相关文章

  1. 短信登录与注册接口、前端所有方式登录注册页面、redis数据库介绍与安装

    今日内容概要 短信登陆接口 短信注册接口 登陆注册前端 redis介绍和安装 内容详细 1.短信登陆接口 在视图类 user/views.py中修改并添加: from .serializer impo ...

  2. python基于LeanCloud的短信验证

    python基于LeanCloud的短信验证 1. 获取LeanCloud的Id.Key 2. 安装Flask框架和Requests库 pip install flask pip install re ...

  3. 基于session和cookie的登录验证(CBV模式)

    基于session和cookie的登录验证(CBV模式) urls.py """cookie_session URL Configuration The `urlpatt ...

  4. Spring Security 解析(四) ——短信登录开发

    Spring Security 解析(四) -- 短信登录开发   在学习Spring Cloud 时,遇到了授权服务oauth 相关内容时,总是一知半解,因此决定先把Spring Security ...

  5. 重构客户注册-基于ActiveMQ实现短信验证码生产者

    重构目标:将bos_fore项目中的CustomerAction作为短信消息生产者,将消息发给ActiveMQ,创建一个单独的SMS项目,作为短信息的消费者,从ActiveMQ获取短信消息,调用第三方 ...

  6. SpringSecurity实现短信登录功能

    ⒈封装短信验证码类 package cn.coreqi.security.validate; import java.time.LocalDateTime; public class Validate ...

  7. 基于PHP实现短信验证码接口的方法

    步骤: 1.登录荣联运通讯注册获取ACCOUNT SID.AUTH TOKEN.Rest URL(生产).AppID(默认): 2.注册测试用手机号码(先注册测试号码方可使用): 3.下载demo示例 ...

  8. Spring Security之短信登录

    实现短信验证码登录 前面实现了 用户名+密码 的登录方式,现在实现一下短信验证码登录. 开发短信验证码接口 短信验证码和图形验证码类似,用户从手机短信得到验证码和从图片得到验证码类似. 校验短信验证码 ...

  9. day102:MoFang:后端完成对短信验证码的校验&基于celery完成异步短信发送&flask_jwt_extended&用户登录的API接口

    目录 1.用户注册 1.后端完成对短信验证码的校验 2.基于celery实现短信异步发送 2.用户登录 1.jwt登录验证:flask_jwt_extended 2.服务端提供用户登录的API接口 1 ...

  10. SpringBoot + Spring Security 学习笔记(五)实现短信验证码+登录功能

    在 Spring Security 中基于表单的认证模式,默认就是密码帐号登录认证,那么对于短信验证码+登录的方式,Spring Security 没有现成的接口可以使用,所以需要自己的封装一个类似的 ...

随机推荐

  1. webpack4.15.1 学习笔记(六) — 代码拆分(Code Splitting)

    目录 入口起点 防止重复 动态导入(dynamic imports) 代码拆分能够将代码分离到不同的 bundle 中,然后可以按需加载或并行加载这些文件.代码拆分可以用于获取更小的 bundle,以 ...

  2. oeasy教您玩转linux010204-figlet

    我们来回顾一下 上一部分我们都讲了什么? 用 apt 查询并下载了 linuxlogo 用字符画出了 linux 发行版的 logo 还查了手册,通过改参数控制输出信息 我们还能玩点什么呢? 这个实验 ...

  3. Django model 层之聚合查询总结

    Django model 层之聚合查询总结 by:授客 QQ:1033553122 实践环境 Python版本:python-3.4.0.amd64 下载地址:https://www.python.o ...

  4. ffmpeg中声音解码的流程

    声音解码流程: audio初始化 fifo初始化frame初始化init_resampler 解码: 如果有帧 初始化转码空间 做转码操作 resampler 放入fifo fifo是否大于 一帧数据 ...

  5. Elasticjob执行job幂等

    ElasticJob的幂等机制,是指作业分片执行的幂等,他需要做到以下两点: 同一个分片在当前作业实例上不会被重复执行 一个作业分片不能同时在多个作业实例上执行 如何实现幂等 场景模拟:存在任务A执行 ...

  6. If Messi doesn't understand how to respect others, then he also doesn't deserve to receive respect from others.

    If Messi doesn't understand how to respect others, if he doesn't understand the spirit of honoring c ...

  7. pytorch的模型推理:TensorRT的使用

    相关教程视频: TRTorch真香,一键启用TensorRT 注意,这里只做入门视频的学习Demo,并没有实际应用的用处. 图片来源:https://www.bilibili.com/video/BV ...

  8. 人工智能Python代码的补全利器 Kite 安装

    代码补全应用kite主要对Python代码进行补全,或者说kite是针对现在的人工智能Python代码(pytorch.tensorflow)等做补全的,而且在Python代码补全上kite可以说是现 ...

  9. php 开发日常收获

    最近项目需求: 仿制某网站的菜单功能 效果如下: 效果大概就是这样啦.分析下吧:主要是分级查询我的思路:首先从数据库中查询所有的顶级目录: 目前就是这几个顶级目录在数据库中特点就是 父级id是0(一般 ...

  10. FlashAttention简介

    前置知识 在GPU进行矩阵运算的时候,内部的运算单元具有和CPU类似的存储金字塔. 如果采用经典的Attention的计算方式,需要保存中间变量S和注意力矩阵O,这样子会产生很大的现存占用,并且这些数 ...