本章内容介绍手机验证码登录
- 点击获取验证码
- 收到短信,并输入验证码
- 点击登录,登录成功
短信发送_短信服务介绍和阿里云短信服务介绍
短信服务介绍
- 目前市面上有很多第三方提供的短信服务,这些第三方短信服务会和各个运营商(移动、联通、电信)对接
- 我们只需要注册成为会员并且按照提供的开发文档进行调用就可以发送短信
-* 需要说明的是*,这些短信服务一般都是收费服务
常用短信服务:
- 阿里云
- 华为云
- 腾讯云
- 京东
- 梦网
- 乐信
本项目中使用:阿里云短信服务(Short Message Service)是广大企业客户快速触达手机用户所优选使用的通信能力。调用API或用群发助手,即可发送验证码、通知类和营销类短信;国内验证短信秒级触达,到达率最高可达99%;国际/港澳台短信覆盖200多个国家和地区,安全稳定,广受出海企业选用。
应用场景:
- 验证码
- 短信通知
- 推广短信
阿里云短信服务介绍
打开浏览器,登录阿里云—网址:https://cn.aliyun.com/
点击产品,在搜索框中输入短信服务,并点击搜索
阿里云短信服务步骤:
第一步:注册账号
第二步:登录
第三步:阿里云短信服务
短信发送_阿里云短信服务
设置短信签名
开通短信服务之后,进入短信服务管理页面,选择国内消息菜单,我们需要在这里添加短信签名
短信签名签名表示短信发送者的身份
什么是短信签名?
- 短信签名是短信发送者的署名,表示发送方的身份
- 我们要调用阿里云短信服务发送短信,签名是必不可少的部分
添加短信签名方式
注意:个人申请签名是有一定的难度的,所以我们只需要了解一下使用短信签名的具体流程
设置短信模板
切换到【模板管理】标签页:
短信模板包含短信发送内容、场景、变量信息
每一个被设置好的模板有一个短信模板详情,模板详情包含了模板的6条信息
添加模板,并且提交后审核通过
一系列步骤,直接省略
短信发送_代码开发_参照官方文档封装发送短信工具类
参照官方文档
使用阿里云短信服务发送短信,可以参照官方提供的文档即可。
具体开发步骤:
- 导入maven坐标
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.5.16</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
<version>2.1.0</version>
</dependency>
2.在reggie包下新建utils包,导入该工具类
package com.itzq.reggie.utils;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
/**
* 短信发送工具类
*/
public class SMSUtils {
/**
* 发送短信
* @param signName 签名
* @param templateCode 模板
* @param phoneNumbers 手机号
* @param param 参数
*/
public static void sendMessage(String signName, String templateCode,String phoneNumbers,String param){
DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", "", "");
IAcsClient client = new DefaultAcsClient(profile);
SendSmsRequest request = new SendSmsRequest();
request.setSysRegionId("cn-hangzhou");
request.setPhoneNumbers(phoneNumbers);
request.setSignName(signName);
request.setTemplateCode(templateCode);
request.setTemplateParam("{\"code\":\""+param+"\"}");
try {
SendSmsResponse response = client.getAcsResponse(request);
System.out.println("短信发送成功");
}catch (ClientException e) {
e.printStackTrace();
}
}
}
查看短信服务产品文档的java SDK,了解短信服务java SDK的使用方法以及示例
手机验证码登录业务开发
- 需求分析
- 数据模型
- 代码开发
- 功能测试
手机验证码登录_需求分析_数据模型
需求分析
为了方便用户登录,移动端通常都会提供通过手机验证码登录的功能
手机验证码登录的优点:
- 方便快捷,无需注册,直接登录
- 使用短信验证码作为登录凭证,无需记忆密码
- 安全
登录流程:
- 输入手机号 > 获取验证码 > 输入验证码 > 点击登录 > 登录成功
注意:通过手机验证码登录,手机号是区分不同用户的标识
用户登录端界面
数据模型
通过手机验证码登录时,涉及的表为user表,即用户表。结构如下:
注意:
- 手机号是区分不同用户的标识,在用户登录的时候判断所输入的手机号是否存储在表中
- 如果不在表中,说明该用户为一个新的用户,将该用户自动保在user表中
手机验证码登录_代码开发_梳理交互过程&修改LoginCheckFilter
梳理交互过程
在开发代码之前,需要梳理一下登录时前端页面和服务端的交互过程:
- 在登录页面(front/page/login.html)输入手机号,点击【获取验证码】按钮,页面发送ajax请求,在服务端调用短信服务API给指定手机号发送验证码短信
- 在登录页面输入验证码,点击【登录】按钮,发送ajax请求,在服务端处理登录请求
开发手机验证码登录功能,其实就是在服务端编写代码去处理前端页面发送的这2次请求即可。
代码开发-准备工作
在开发业务功能前,先将需要用到的类和接口基本结构创建好:
- 实体类user (直接从课程资料中导入即可)
- Mapper接口UserMapper
- 业务层接口UserService
- 业务层实现类UserServicelmpl
- 控制层UserController
- 工具类SMSutils、ValidateCodeutils(直接从课程资料中导入即可)
在LoginCheckFilter类下添加代码,判断用户是否登录
//4-2 判断登录状态,如果已登录,则直接放行
if(request.getSession().getAttribute("user") != null){
log.info("用户已登录,用户id为:{}",request.getSession().getAttribute("user"));
Long userId = (Long)request.getSession().getAttribute("user");
BaseContext.setCurrentId(userId);
filterChain.doFilter(request,response);
return;
手机验证码登录_代码开发_发送验证码短信
代码开发
注意
- 发送短信只需要调用封装的工具类中的方法即可
- 使用手机号登录功能流程跑通,在测试中我们不用真正的发送短信,只需要将验证码信息,通过日志输出
- 登录时,我们直接从控制台就可以看到生成的验证码(实际上也就是发送到我们手机上的验证码)
在UserController控制层中,添加sendMsg方法
@PostMapping("/sendMsg")
public R<String> sendMsg(@RequestBody User user, HttpSession session){
//获取手机号
String phone = user.getPhone();
if (StringUtils.isNotEmpty(phone)){
//生成随机的4位验证码
String code = ValidateCodeUtils.generateValidateCode4String(4);
log.info("code={}",code);
//调用阿里云提供的短信服务API完成短信发送
//SMSUtils.sendMessage("瑞吉外卖","",phone,code);
//需要将生成的验证码保存到session
session.setAttribute(phone,code);
return R.success("短信发送成功");
}
return R.error("短信发送失败");
}
在UserController控制层类中,添加login方法,测试服务端是否可以接受前端提交的数据
@PostMapping("/login")
public R<String> login(@RequestBody Map map, HttpSession session){
log.info(map.toString());
return R.error("短信发送失败");
}
完善用户登录代码
@PostMapping("/login")
public R<User> login(@RequestBody Map map, HttpSession session){
log.info(map.toString());
//获取手机号
String phone = map.get("phone").toString();
//获取验证码
String code = map.get("code").toString();
//从session中获取保存的验证码
String codeInSession = session.getAttribute(phone).toString();
//进行验证码的对比(页面提交的验证码和session中保存的验证码)
if (code != null && code.equals(codeInSession)){
//如果比对成功,则登录成功
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(User::getPhone,phone);
User user = userService.getOne(queryWrapper);
if (user == null){
//判断当前手机号是否为新用户,如果是新用户则自动完成注入
user = new User();
user.setPhone(phone);
userService.save(user);
}
return R.success(user);
}
return R.error("登录失败");
}
重启项目,在用户登录页面输入手机号,和获取到的验证码,点击登录
页面成功跳转到服务用户界面
user表中成功添加上测试的手机号码(未注册的手机号码)