目录

4. 短信发送​编辑

4.1 短信服务介绍

4.2 阿里云短信服务介绍

4.3 阿里云短信服务准备

4.4 代码开发

5. 手机验证码登录

5.1 需求分析

5.2 数据模型

5.3 前端页面分析

5.4 代码开发

5.5 功能测试


4. 短信发送

在我们接下来要实现的移动端的业务开发中,第一块儿我们需要开发的功能就是移动端的登录功能,而移动端的登录功能,比较流行的方式就是基于短信验证码进行登录,那么这里涉及到了短信发送的知识,所以本章节,我们就来讲解,在项目开发中,我们如何发送短信。

4.1 短信服务介绍

在项目中,如果我们要实现短信发送功能,我们无需自己实现,也无需和运营商直接对接,只需要调用第三方提供的短信服务即可。目前市面上有很多第三方提供的短信服务,这些第三方短信服务会和各个运营商(移动、联通、电信)对接,我们只需要注册成为会员,并且按照提供的开发文档进行调用就可以发送短信。需要说明的是,这些短信服务一般都是收费服务。

常用短信服务:

  • 阿里云

  • 华为云

  • 腾讯云

  • 京东

  • 梦网

  • 乐信

本项目在选择短信服务的第三方服务提供商时,选择的是阿里云短信服务。

4.2 阿里云短信服务介绍

阿里云短信服务(Short Message Service)是广大企业客户快速触达手机用户所优选使用的通信能力。调用API或用群发助手,即可发送验证码、通知类和营销类短信;国内验证短信秒级触达,到达率最高可达99%;国际/港澳台短信覆盖200多个国家和地区,安全稳定,广受出海企业选用。

应用场景:

场景 案例
验证码 APP、网站注册账号,向手机下发验证码; 登录账户、异地登录时的安全提醒; 找回密码时的安全验证; 支付认证、身份校验、手机绑定等。
短信通知 向注册用户下发系统相关信息,包括: 升级或维护、服务开通、价格调整、 订单确认、物流动态、消费确认、 支付通知等普通通知短信。
推广短信 向注册用户和潜在客户发送通知和推广信息,包括促销活动通知、业务推广等商品与活动的推广信息。增加企业产品曝光率、提高产品的知名度。

阿里云短信服务官方网站: 短信服务_企业短信营销推广_验证码通知-阿里云

可以访问官网,熟悉一下短信服务:

4.3 阿里云短信服务准备

4.3.1 注册账号

阿里云官网:https://www.aliyun.com/

点击官网首页注册按钮,跳转到如下注册页面:

当我们把账号注册完毕之后,我们就可以登录到阿里云系统控制台。

4.3.2 开通短信服务

注册成功后,点击登录按钮进行登录。登录后进入控制台, 在左上角的菜单栏中搜索短信服务。第一次使用,需要点击,并开通短信服务。

4.3.3 设置短信签名

开通短信服务之后,进入短信服务管理页面,选择国内消息菜单,我们需要在这里添加短信签名。

那么什么是短信签名呢?

短信签名是短信发送者的署名,表示发送方的身份。我们要调用阿里云短信服务发送短信,签名是比不可少的部分。

那么接下来,我们就需要来添加短信签名。

注意:

目前,阿里云短信服务申请签名主要针对企业开发,个人申请时有一定难度的,在审核时,会审核资质,需要上传营业执照 ;

所以,我们课程中,主要是演示一下短信验证码如何发送,大家只需要学习这块儿的开发流程、实现方式即可,无需真正的发送短信。如果以后在企业中做项目,需要发送短信,我们会以公司的资质去申请对应的签名。

4.3.4 设置短信模板

切换到【模板管理】标签页:

那么什么是模板呢?

短信模板包含短信发送内容、场景、变量信息。模板的详情如下:

最终我们,给用户发送的短信中,具体的短信内容,就是上面配置的这个模板内容,将${code}占位符替换成对应的验证码数据即可。如下:

<span style="background-color:#f8f8f8"><span style="color:#333333">【xxxxx】您好,您的验证码为173822,5分钟之内有效,不要泄露给他人!</span></span>

我们可以点击右上角的按钮,添加模板,然后填写模板的基本信息及设置的模板内容:

添加的短信模板,也是需要进行审核的只有审核通过,才可以正常使用。

4.3.5 设置AccessKey

AccessKey 是访问阿里云 API 的密钥,具有账户的完全权限,我们要想在后面通过API调用阿里云短信服务的接口发送短信,那么就必须要设置AccessKey。

我们点击右上角的用户头像,选择"AccessKey管理",这时就可以进入到AccessKey的管理界面。

进入到AccessKey的管理界面之后,提示两个选项 "继续使用AccessKey" 和 "开始使用子用户AccessKey",两个区别如下:

1). 继续使用AccessKey

如果选择的是该选项,我们创建的是阿里云账号的AccessKey,是具有账户的完全权限,有了这个AccessKey以后,我们就可以通过API调用阿里云的服务,不仅是短信服务,其他服务(OSS,语音服务,内容安全服务,视频点播服务...等)也可以调用。 相对来说,并不安全,当前的AccessKey泄露,会影响到我当前账户的其他云服务。

2). 开始使用子用户AccessKey

可以创建一个子用户,这个子用户我们可以分配比较低的权限,比如仅分配短信发送的权限,不具备操作其他的服务的权限,即使这个AccessKey泄漏了,也不会影响其他的云服务, 相对安全。

接下来就来演示一下,如何创建子用户AccessKey。

4.3.6 配置权限

上述我们已经创建了子用户, 但是这个子用户,目前没有任何权限,接下来,我们需要为创建的这个用户来分配权限。

经过上述的权限配置之后,那么新创建的这个 reggie 用户,仅有短信服务操作的权限,不具备别的权限,即使当前的AccessKey泄漏了,也只会影响短信服务,其他服务是不受影响的。

4.3.7 禁用/删除AccessKey

如果在使用的过程中 AccessKey 不小心泄漏了,我们可以在阿里云控制台中, 禁用或者删除该AccessKey。

然后再创建一个新的AccessKey, 保存好AccessKeyId和AccessKeySecret。

==注意: 创建好了AccessKey后,请及时保存AccessKeyId 和 AccessKeySecret ,弹窗关闭后将无法再次获取该信息,但您可以随时创建新的 AccessKey。==

4.4 代码开发

使用阿里云短信服务发送短信,可以参照官方提供的文档即可。

官方文档: 短信服务 - 帮助中心 - 阿里云

我们根据官方文档的提示,引入对应的依赖,然后再引入对应的java代码,就可以发送消息了。

SDK : SDK 就是 Software Development Kit 的缩写,翻译过来——软件开发工具包,辅助开发某一类软件的相关文档、范例和工具的集合都可以叫做SDK。在我们与第三方接口相互时, 一般都会提供对应的SDK,来简化我们的开发。

具体实现:

1). pom.xml

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#117700"><</span><span style="color:#117700">dependency</span><span style="color:#117700">></span><span style="color:#117700"><</span><span style="color:#117700">groupId</span><span style="color:#117700">></span><span style="color:var(--select-text-font-color) !important">com.aliyun</span><span style="color:#117700"></</span><span style="color:#117700">groupId</span><span style="color:#117700">></span><span style="color:#117700"><</span><span style="color:#117700">artifactId</span><span style="color:#117700">></span><span style="color:var(--select-text-font-color) !important">aliyun-java-sdk-core</span><span style="color:#117700"></</span><span style="color:#117700">artifactId</span><span style="color:#117700">></span><span style="color:#117700"><</span><span style="color:#117700">version</span><span style="color:#117700">></span><span style="color:var(--select-text-font-color) !important">4.5.16</span><span style="color:#117700"></</span><span style="color:#117700">version</span><span style="color:#117700">></span>
<span style="color:#117700"></</span><span style="color:#117700">dependency</span><span style="color:#117700">></span>
<span style="color:#117700"><</span><span style="color:#117700">dependency</span><span style="color:#117700">></span><span style="color:#117700"><</span><span style="color:#117700">groupId</span><span style="color:#117700">></span><span style="color:var(--select-text-font-color) !important">com.aliyun</span><span style="color:#117700"></</span><span style="color:#117700">groupId</span><span style="color:#117700">></span><span style="color:#117700"><</span><span style="color:#117700">artifactId</span><span style="color:#117700">></span><span style="color:var(--select-text-font-color) !important">aliyun-java-sdk-dysmsapi</span><span style="color:#117700"></</span><span style="color:#117700">artifactId</span><span style="color:#117700">></span><span style="color:#117700"><</span><span style="color:#117700">version</span><span style="color:#117700">></span><span style="color:var(--select-text-font-color) !important">2.1.0</span><span style="color:#117700"></</span><span style="color:#117700">version</span><span style="color:#117700">></span>
<span style="color:#117700"></</span><span style="color:#117700">dependency</span><span style="color:#117700">></span></span></span>

2). 将官方提供的main方法封装为一个工具类

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#770088">import</span> <span style="color:#000000">com</span>.<span style="color:#000000">aliyuncs</span>.<span style="color:#000000">DefaultAcsClient</span>;
<span style="color:#770088">import</span> <span style="color:#000000">com</span>.<span style="color:#000000">aliyuncs</span>.<span style="color:#000000">IAcsClient</span>;
<span style="color:#770088">import</span> <span style="color:#000000">com</span>.<span style="color:#000000">aliyuncs</span>.<span style="color:#000000">dysmsapi</span>.<span style="color:#000000">model</span>.<span style="color:#000000">v20170525</span>.<span style="color:#000000">SendSmsRequest</span>;
<span style="color:#770088">import</span> <span style="color:#000000">com</span>.<span style="color:#000000">aliyuncs</span>.<span style="color:#000000">dysmsapi</span>.<span style="color:#000000">model</span>.<span style="color:#000000">v20170525</span>.<span style="color:#000000">SendSmsResponse</span>;
<span style="color:#770088">import</span> <span style="color:#000000">com</span>.<span style="color:#000000">aliyuncs</span>.<span style="color:#000000">exceptions</span>.<span style="color:#000000">ClientException</span>;
<span style="color:#770088">import</span> <span style="color:#000000">com</span>.<span style="color:#000000">aliyuncs</span>.<span style="color:#000000">profile</span>.<span style="color:#000000">DefaultProfile</span>;
​
<span style="color:#aa5500">/**</span><span style="color:#aa5500">* 短信发送工具类</span><span style="color:#aa5500">*/</span>
<span style="color:#770088">public</span> <span style="color:#770088">class</span> <span style="color:#0000ff">SMSUtils</span> {<span style="color:#aa5500">/**</span><span style="color:#aa5500">* 发送短信</span><span style="color:#aa5500">* @param signName 签名</span><span style="color:#aa5500">* @param templateCode 模板</span><span style="color:#aa5500">* @param phoneNumbers 手机号</span><span style="color:#aa5500">* @param param 参数</span><span style="color:#aa5500">*/</span><span style="color:#770088">public</span> <span style="color:#770088">static</span> <span style="color:#008855">void</span> <span style="color:#000000">sendMessage</span>(<span style="color:#008855">String</span> <span style="color:#000000">signName</span>, <span style="color:#008855">String</span> <span style="color:#000000">templateCode</span>,<span style="color:#008855">String</span> <span style="color:#000000">phoneNumbers</span>,<span style="color:#008855">String</span> <span style="color:#000000">param</span>){<span style="color:#000000">DefaultProfile</span> <span style="color:#000000">profile</span> <span style="color:#981a1a">=</span> <span style="color:#000000">DefaultProfile</span>.<span style="color:#000000">getProfile</span>(<span style="color:#aa1111">"cn-hangzhou"</span>, <span style="color:#aa1111">"xxxxxxxxxxxxxxxx"</span>, <span style="color:#aa1111">"xxxxxxxxxxxxxx"</span>);<span style="color:#000000">IAcsClient</span> <span style="color:#000000">client</span> <span style="color:#981a1a">=</span> <span style="color:#770088">new</span> <span style="color:#000000">DefaultAcsClient</span>(<span style="color:#000000">profile</span>);
​<span style="color:#000000">SendSmsRequest</span> <span style="color:#000000">request</span> <span style="color:#981a1a">=</span> <span style="color:#770088">new</span> <span style="color:#000000">SendSmsRequest</span>();<span style="color:#000000">request</span>.<span style="color:#000000">setSysRegionId</span>(<span style="color:#aa1111">"cn-hangzhou"</span>);<span style="color:#000000">request</span>.<span style="color:#000000">setPhoneNumbers</span>(<span style="color:#000000">phoneNumbers</span>);<span style="color:#000000">request</span>.<span style="color:#000000">setSignName</span>(<span style="color:#000000">signName</span>);<span style="color:#000000">request</span>.<span style="color:#000000">setTemplateCode</span>(<span style="color:#000000">templateCode</span>);<span style="color:#000000">request</span>.<span style="color:#000000">setTemplateParam</span>(<span style="color:#aa1111">"{\"code\":\""</span><span style="color:#981a1a">+</span><span style="color:#000000">param</span><span style="color:#981a1a">+</span><span style="color:#aa1111">"\"}"</span>);<span style="color:#770088">try</span> {<span style="color:#000000">SendSmsResponse</span> <span style="color:#000000">response</span> <span style="color:#981a1a">=</span> <span style="color:#000000">client</span>.<span style="color:#000000">getAcsResponse</span>(<span style="color:#000000">request</span>);<span style="color:#000000">System</span>.<span style="color:#000000">out</span>.<span style="color:#000000">println</span>(<span style="color:#aa1111">"短信发送成功"</span>);}<span style="color:#770088">catch</span> (<span style="color:#000000">ClientException</span> <span style="color:#000000">e</span>) {<span style="color:#000000">e</span>.<span style="color:#000000">printStackTrace</span>();}}
​
}</span></span>

备注 : 由于我们个人目前无法申请阿里云短信服务,所以这里我们只需要把流程跑通,具体的短信发送可以实现。

5. 手机验证码登录

5.1 需求分析

为了方便用户登录,移动端通常都会提供通过手机验证码登录的功能。手机验证码登录有如下优点:

1). 方便快捷,无需注册,直接登录

2). 使用短信验证码作为登录凭证,无需记忆密码

3). 安全

登录流程:

输入手机号 > 获取验证码 > 输入验证码 > 点击登录 > 登录成功

注意:通过手机验证码登录,手机号是区分不同用户的标识。

5.2 数据模型

通过手机验证码登录时,涉及的表为user表,即用户表。结构如下:

5.3 前端页面分析

在开发代码之前,需要梳理一下登录时前端页面和服务端的交互过程:

1). 在登录页面(front/page/login.html)输入手机号,点击【获取验证码】按钮,页面发送ajax请求,在服务端调用短信服务API给指定手机号发送验证码短信。

2). 在登录页面输入验证码,点击【登录】按钮,发送ajax请求,在服务端处理登录请求。

如果服务端返回的登录成功,页面将会把当前登录用户的手机号存储在sessionStorage中,并跳转到移动的首页页面。

开发手机验证码登录功能,其实就是在服务端编写代码去处理前端页面发送的这2次请求即可,分别是获取短信验证码 和 登录请求,具体的请求信息如下:

1). 获取短信验证码

请求 说明
请求方式 POST
请求路径 /user/sendMsg
请求参数 {"phone":"13100001111"}

2). 登录

请求 说明
请求方式 POST
请求路径 /user/login
请求参数 {"phone":"13100001111", "code":"1111"}

5.4 代码开发

5.4.1 准备工作

在开发业务功能前,先将需要用到的类和接口基本结构创建好:

1). 实体类 User(直接从课程资料中导入即可)

所属包: com.itheima.reggie.entity

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#770088">import</span> <span style="color:#000000">lombok</span>.<span style="color:#000000">Data</span>;
<span style="color:#770088">import</span> <span style="color:#000000">java</span>.<span style="color:#000000">io</span>.<span style="color:#000000">Serializable</span>;
<span style="color:#aa5500">/**</span><span style="color:#aa5500">* 用户信息</span><span style="color:#aa5500">*/</span>
<span style="color:#555555">@Data</span>
<span style="color:#770088">public</span> <span style="color:#770088">class</span> <span style="color:#0000ff">User</span> <span style="color:#770088">implements</span> <span style="color:#000000">Serializable</span> {<span style="color:#770088">private</span> <span style="color:#770088">static</span> <span style="color:#770088">final</span> <span style="color:#008855">long</span> <span style="color:#000000">serialVersionUID</span> <span style="color:#981a1a">=</span> <span style="color:#116644">1L</span>;
​<span style="color:#770088">private</span> <span style="color:#008855">Long</span> <span style="color:#000000">id</span>;
​<span style="color:#aa5500">//姓名</span><span style="color:#770088">private</span> <span style="color:#008855">String</span> <span style="color:#000000">name</span>;
​<span style="color:#aa5500">//手机号</span><span style="color:#770088">private</span> <span style="color:#008855">String</span> <span style="color:#000000">phone</span>;
​<span style="color:#aa5500">//性别 0 女 1 男</span><span style="color:#770088">private</span> <span style="color:#008855">String</span> <span style="color:#000000">sex</span>;
​<span style="color:#aa5500">//身份证号</span><span style="color:#770088">private</span> <span style="color:#008855">String</span> <span style="color:#000000">idNumber</span>;
​<span style="color:#aa5500">//头像</span><span style="color:#770088">private</span> <span style="color:#008855">String</span> <span style="color:#000000">avatar</span>;
​<span style="color:#aa5500">//状态 0:禁用,1:正常</span><span style="color:#770088">private</span> <span style="color:#008855">Integer</span> <span style="color:#000000">status</span>;
}</span></span>

2). Mapper接口 UserMapper

所属包: com.itheima.reggie.mapper

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#770088">import</span> <span style="color:#000000">com</span>.<span style="color:#000000">baomidou</span>.<span style="color:#000000">mybatisplus</span>.<span style="color:#000000">core</span>.<span style="color:#000000">mapper</span>.<span style="color:#000000">BaseMapper</span>;
<span style="color:#770088">import</span> <span style="color:#000000">com</span>.<span style="color:#000000">itheima</span>.<span style="color:#000000">reggie</span>.<span style="color:#000000">entity</span>.<span style="color:#000000">User</span>;
<span style="color:#770088">import</span> <span style="color:#000000">org</span>.<span style="color:#000000">apache</span>.<span style="color:#000000">ibatis</span>.<span style="color:#000000">annotations</span>.<span style="color:#000000">Mapper</span>;
​
<span style="color:#555555">@Mapper</span>
<span style="color:#770088">public</span> <span style="color:#770088">interface</span> <span style="color:#0000ff">UserMapper</span> <span style="color:#770088">extends</span> <span style="color:#000000">BaseMapper</span><span style="color:#981a1a"><</span><span style="color:#000000">User</span><span style="color:#981a1a">></span>{
}</span></span>

3). 业务层接口 UserService

所属包: com.itheima.reggie.service

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#770088">import</span> <span style="color:#000000">com</span>.<span style="color:#000000">baomidou</span>.<span style="color:#000000">mybatisplus</span>.<span style="color:#000000">extension</span>.<span style="color:#000000">service</span>.<span style="color:#000000">IService</span>;
<span style="color:#770088">import</span> <span style="color:#000000">com</span>.<span style="color:#000000">itheima</span>.<span style="color:#000000">reggie</span>.<span style="color:#000000">entity</span>.<span style="color:#000000">User</span>;
​
<span style="color:#770088">public</span> <span style="color:#770088">interface</span> <span style="color:#0000ff">UserService</span> <span style="color:#770088">extends</span> <span style="color:#000000">IService</span><span style="color:#981a1a"><</span><span style="color:#000000">User</span><span style="color:#981a1a">></span> {
}</span></span>

4). 业务层实现类 UserServiceImpl

所属包: com.itheima.reggie.service.impl

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#770088">import</span> <span style="color:#000000">com</span>.<span style="color:#000000">baomidou</span>.<span style="color:#000000">mybatisplus</span>.<span style="color:#000000">extension</span>.<span style="color:#000000">service</span>.<span style="color:#000000">impl</span>.<span style="color:#000000">ServiceImpl</span>;
<span style="color:#770088">import</span> <span style="color:#000000">com</span>.<span style="color:#000000">itheima</span>.<span style="color:#000000">reggie</span>.<span style="color:#000000">entity</span>.<span style="color:#000000">User</span>;
<span style="color:#770088">import</span> <span style="color:#000000">com</span>.<span style="color:#000000">itheima</span>.<span style="color:#000000">reggie</span>.<span style="color:#000000">mapper</span>.<span style="color:#000000">UserMapper</span>;
<span style="color:#770088">import</span> <span style="color:#000000">com</span>.<span style="color:#000000">itheima</span>.<span style="color:#000000">reggie</span>.<span style="color:#000000">service</span>.<span style="color:#000000">UserService</span>;
<span style="color:#770088">import</span> <span style="color:#000000">org</span>.<span style="color:#000000">springframework</span>.<span style="color:#000000">stereotype</span>.<span style="color:#000000">Service</span>;
​
<span style="color:#555555">@Service</span>
<span style="color:#770088">public</span> <span style="color:#770088">class</span> <span style="color:#0000ff">UserServiceImpl</span> <span style="color:#770088">extends</span> <span style="color:#000000">ServiceImpl</span><span style="color:#981a1a"><</span><span style="color:#000000">UserMapper</span>,<span style="color:#000000">User</span><span style="color:#981a1a">></span> <span style="color:#770088">implements</span> <span style="color:#000000">UserService</span>{
}</span></span>

5). 控制层 UserController

所属包: com.itheima.reggie.controller

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#770088">import</span> <span style="color:#000000">com</span>.<span style="color:#000000">itheima</span>.<span style="color:#000000">reggie</span>.<span style="color:#000000">service</span>.<span style="color:#000000">UserService</span>;
<span style="color:#770088">import</span> <span style="color:#000000">lombok</span>.<span style="color:#000000">extern</span>.<span style="color:#000000">slf4j</span>.<span style="color:#000000">Slf4j</span>;
<span style="color:#770088">import</span> <span style="color:#000000">org</span>.<span style="color:#000000">springframework</span>.<span style="color:#000000">beans</span>.<span style="color:#000000">factory</span>.<span style="color:#000000">annotation</span>.<span style="color:#000000">Autowired</span>;
<span style="color:#770088">import</span> <span style="color:#000000">org</span>.<span style="color:#000000">springframework</span>.<span style="color:#000000">web</span>.<span style="color:#000000">bind</span>.<span style="color:#000000">annotation</span>.<span style="color:#000000">RequestMapping</span>;
<span style="color:#770088">import</span> <span style="color:#000000">org</span>.<span style="color:#000000">springframework</span>.<span style="color:#000000">web</span>.<span style="color:#000000">bind</span>.<span style="color:#000000">annotation</span>.<span style="color:#000000">RestController</span>;
​
<span style="color:#555555">@RestController</span>
<span style="color:#555555">@RequestMapping</span>(<span style="color:#aa1111">"/user"</span>)
<span style="color:#555555">@Slf4j</span>
<span style="color:#770088">public</span> <span style="color:#770088">class</span> <span style="color:#0000ff">UserController</span> {<span style="color:#555555">@Autowired</span><span style="color:#770088">private</span> <span style="color:#000000">UserService</span> <span style="color:#000000">userService</span>;
}</span></span>

6). 工具类SMSUtils、ValidateCodeUtils(直接从课程资料中导入即可)

所属包: com.itheima.reggie.utils

SMSUtils : 是我们上面改造的阿里云短信发送的工具类 ;

ValidateCodeUtils : 是验证码生成的工具类 ;

5.4.2 功能实现

5.4.2.1 修改LoginCheckFilter

前面我们已经完成了LoginCheckFilter过滤器的开发,此过滤器用于检查用户的登录状态。我们在进行手机验证码登录时,发送的两个请求(获取验证码和登录)需要在此过滤器处理时直接放行。

对于移动的端的页面,也是用户登录之后,才可以访问的,那么这个时候就需要在 LoginCheckFilter 中进行判定,如果移动端用户已登录,我们获取到用户登录信息,存入ThreadLocal中(在后续的业务处理中,如果需要获取当前登录用户ID,直接从ThreadLocal中获取),然后放行。

增加如下逻辑:

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#aa5500">//4-2、判断登录状态,如果已登录,则直接放行</span>
<span style="color:#770088">if</span>(<span style="color:#000000">request</span>.<span style="color:#000000">getSession</span>().<span style="color:#000000">getAttribute</span>(<span style="color:#aa1111">"user"</span>) <span style="color:#981a1a">!=</span> <span style="color:#221199">null</span>){<span style="color:#000000">log</span>.<span style="color:#000000">info</span>(<span style="color:#aa1111">"用户已登录,用户id为:{}"</span>,<span style="color:#000000">request</span>.<span style="color:#000000">getSession</span>().<span style="color:#000000">getAttribute</span>(<span style="color:#aa1111">"user"</span>));
​<span style="color:#008855">Long</span> <span style="color:#000000">userId</span> <span style="color:#981a1a">=</span> (<span style="color:#008855">Long</span>) <span style="color:#000000">request</span>.<span style="color:#000000">getSession</span>().<span style="color:#000000">getAttribute</span>(<span style="color:#aa1111">"user"</span>);<span style="color:#000000">BaseContext</span>.<span style="color:#000000">setCurrentId</span>(<span style="color:#000000">userId</span>);
​<span style="color:#000000">filterChain</span>.<span style="color:#000000">doFilter</span>(<span style="color:#000000">request</span>,<span style="color:#000000">response</span>);<span style="color:#770088">return</span>;
}</span></span>

5.4.2.2 发送短信验证码

在UserController中创建方法,处理登录页面的请求,为指定手机号发送短信验证码,同时需要将手机号对应的验证码保存到Session,方便后续登录时进行比对。

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#aa5500">/**</span><span style="color:#aa5500">* 发送手机短信验证码</span><span style="color:#aa5500">* @param user</span><span style="color:#aa5500">* @return</span><span style="color:#aa5500">*/</span>
<span style="color:#555555">@PostMapping</span>(<span style="color:#aa1111">"/sendMsg"</span>)
<span style="color:#770088">public</span> <span style="color:#000000">R</span><span style="color:#981a1a"><</span><span style="color:#008855">String</span><span style="color:#981a1a">></span> <span style="color:#0000ff">sendMsg</span>(<span style="color:#555555">@RequestBody</span> <span style="color:#000000">User</span> <span style="color:#000000">user</span>, <span style="color:#000000">HttpSession</span> <span style="color:#000000">session</span>){<span style="color:#aa5500">//获取手机号</span><span style="color:#008855">String</span> <span style="color:#000000">phone</span> <span style="color:#981a1a">=</span> <span style="color:#000000">user</span>.<span style="color:#000000">getPhone</span>();<span style="color:#770088">if</span>(<span style="color:#000000">StringUtils</span>.<span style="color:#000000">isNotEmpty</span>(<span style="color:#000000">phone</span>)){<span style="color:#aa5500">//生成随机的4位验证码</span><span style="color:#008855">String</span> <span style="color:#000000">code</span> <span style="color:#981a1a">=</span> <span style="color:#000000">ValidateCodeUtils</span>.<span style="color:#000000">generateValidateCode</span>(<span style="color:#116644">4</span>).<span style="color:#000000">toString</span>();<span style="color:#000000">log</span>.<span style="color:#000000">info</span>(<span style="color:#aa1111">"code={}"</span>,<span style="color:#000000">code</span>);<span style="color:#aa5500">//调用阿里云提供的短信服务API完成发送短信</span><span style="color:#aa5500">//SMSUtils.sendMessage("瑞吉外卖","",phone,code);</span><span style="color:#aa5500">//需要将生成的验证码保存到Session</span><span style="color:#000000">session</span>.<span style="color:#000000">setAttribute</span>(<span style="color:#000000">phone</span>,<span style="color:#000000">code</span>);<span style="color:#770088">return</span> <span style="color:#000000">R</span>.<span style="color:#000000">success</span>(<span style="color:#aa1111">"手机验证码短信发送成功"</span>);}<span style="color:#770088">return</span> <span style="color:#000000">R</span>.<span style="color:#000000">error</span>(<span style="color:#aa1111">"短信发送失败"</span>);
}</span></span>

备注:

这里发送短信我们只需要调用封装的工具类中的方法即可,我们这个功能流程跑通,在测试中我们不用真正的发送短信,只需要将验证码信息,通过日志输出,登录时,我们直接从控制台就可以看到生成的验证码(实际上也就是发送到我们手机上的验证码)

5.4.2.3 验证码登录

在UserController中增加登录的方法 login,该方法的具体逻辑为:

1). 获取前端传递的手机号和验证码

2). 从Session中获取到手机号对应的正确的验证码

3). 进行验证码的比对 , 如果比对失败, 直接返回错误信息

4). 如果比对成功, 需要根据手机号查询当前用户, 如果用户不存在, 则自动注册一个新用户

5). 将登录用户的ID存储Session中

具体代码实现:

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#aa5500">/**</span><span style="color:#aa5500">* 移动端用户登录</span><span style="color:#aa5500">* @param map</span><span style="color:#aa5500">* @param session</span><span style="color:#aa5500">* @return</span><span style="color:#aa5500">*/</span>
<span style="color:#555555">@PostMapping</span>(<span style="color:#aa1111">"/login"</span>)
<span style="color:#770088">public</span> <span style="color:#000000">R</span><span style="color:#981a1a"><</span><span style="color:#000000">User</span><span style="color:#981a1a">></span> <span style="color:#0000ff">login</span>(<span style="color:#555555">@RequestBody</span> <span style="color:#000000">Map</span> <span style="color:#000000">map</span>, <span style="color:#000000">HttpSession</span> <span style="color:#000000">session</span>){<span style="color:#000000">log</span>.<span style="color:#000000">info</span>(<span style="color:#000000">map</span>.<span style="color:#000000">toString</span>());<span style="color:#aa5500">//获取手机号</span><span style="color:#008855">String</span> <span style="color:#000000">phone</span> <span style="color:#981a1a">=</span> <span style="color:#000000">map</span>.<span style="color:#000000">get</span>(<span style="color:#aa1111">"phone"</span>).<span style="color:#000000">toString</span>();<span style="color:#aa5500">//获取验证码</span><span style="color:#008855">String</span> <span style="color:#000000">code</span> <span style="color:#981a1a">=</span> <span style="color:#000000">map</span>.<span style="color:#000000">get</span>(<span style="color:#aa1111">"code"</span>).<span style="color:#000000">toString</span>();<span style="color:#aa5500">//从Session中获取保存的验证码</span><span style="color:#008855">Object</span> <span style="color:#000000">codeInSession</span> <span style="color:#981a1a">=</span> <span style="color:#000000">session</span>.<span style="color:#000000">getAttribute</span>(<span style="color:#000000">phone</span>);
​<span style="color:#aa5500">//进行验证码的比对(页面提交的验证码和Session中保存的验证码比对)</span><span style="color:#770088">if</span>(<span style="color:#000000">codeInSession</span> <span style="color:#981a1a">!=</span> <span style="color:#221199">null</span> <span style="color:#981a1a">&&</span> <span style="color:#000000">codeInSession</span>.<span style="color:#000000">equals</span>(<span style="color:#000000">code</span>)){<span style="color:#aa5500">//如果能够比对成功,说明登录成功</span>
​<span style="color:#000000">LambdaQueryWrapper</span><span style="color:#981a1a"><</span><span style="color:#000000">User</span><span style="color:#981a1a">></span> <span style="color:#000000">queryWrapper</span> <span style="color:#981a1a">=</span> <span style="color:#770088">new</span> <span style="color:#000000">LambdaQueryWrapper</span><span style="color:#981a1a"><></span>();<span style="color:#000000">queryWrapper</span>.<span style="color:#000000">eq</span>(<span style="color:#000000">User</span>::<span style="color:#000000">getPhone</span>,<span style="color:#000000">phone</span>);
​<span style="color:#000000">User</span> <span style="color:#000000">user</span> <span style="color:#981a1a">=</span> <span style="color:#000000">userService</span>.<span style="color:#000000">getOne</span>(<span style="color:#000000">queryWrapper</span>);<span style="color:#770088">if</span>(<span style="color:#000000">user</span> <span style="color:#981a1a">==</span> <span style="color:#221199">null</span>){<span style="color:#aa5500">//判断当前手机号对应的用户是否为新用户,如果是新用户就自动完成注册</span><span style="color:#000000">user</span> <span style="color:#981a1a">=</span> <span style="color:#770088">new</span> <span style="color:#000000">User</span>();<span style="color:#000000">user</span>.<span style="color:#000000">setPhone</span>(<span style="color:#000000">phone</span>);<span style="color:#000000">user</span>.<span style="color:#000000">setStatus</span>(<span style="color:#116644">1</span>);<span style="color:#000000">userService</span>.<span style="color:#000000">save</span>(<span style="color:#000000">user</span>);}<span style="color:#000000">session</span>.<span style="color:#000000">setAttribute</span>(<span style="color:#aa1111">"user"</span>,<span style="color:#000000">user</span>.<span style="color:#000000">getId</span>());<span style="color:#770088">return</span> <span style="color:#000000">R</span>.<span style="color:#000000">success</span>(<span style="color:#000000">user</span>);}<span style="color:#770088">return</span> <span style="color:#000000">R</span>.<span style="color:#000000">error</span>(<span style="color:#aa1111">"登录失败"</span>);
}</span></span>

5.5 功能测试

代码完成后,重启服务,测试短信验证码的发送及登录功能。

1). 测试错误验证码的情况

2). 测试正确验证码的情况

检查user表,用户的数据也插入进来了:

【瑞吉外卖】day08:短信发送、手机验证码登录相关推荐

  1. 阿里大于短信——发送手机验证码

    使用阿里大于的短信服务需要先去开通相应服务,具体过程:https://www.jb51.net/article/171902.htm,https://www.cnblogs.com/shubs/p/1 ...

  2. C#使用极光短信发送手机验证码

    引用极光官方类库,或下载提供的资源. JpushEvents.cs using System; using System.Collections.Generic; using System.Linq; ...

  3. 【阿里短信发送DEMO】阿里短信发送获取验证码

    代码可以用,希望能帮到你 import io.seata.common.util.StringUtils; import io.swagger.annotations.Api; import io.s ...

  4. Java实战项目《瑞吉外卖》

    目录 <瑞吉外卖>后台管理系统开发 软件开发整体介绍 1.软件开发流程 2.角色分工 3.软件环境 瑞吉外卖项目介绍 1.项目介绍 2.产品原型展示 3.技术选型 4.功能架构 5.角色 ...

  5. 瑞吉外卖-Day01

    瑞吉外卖-Day01 课程内容 软件开发整体介绍 瑞吉外卖项目介绍 开发环境搭建 后台登录功能开发 后台退出功能开发 1. 软件开发整体介绍 作为一名软件开发工程师,我们需要了解在软件开发过程中的开发 ...

  6. 瑞吉外卖项目中手机短信验证登录的问题及过程处理

    瑞吉外卖中手机短信验证码登陆的问题以及过程整理 本篇接上一篇文章: <基于SpringBoot+MybatisPlus开发的外卖管理项目>戳戳戳 http://t.csdn.cn/cRJY ...

  7. 【瑞吉外卖】发送短信验证码功能实现

    1.先申请微信的订阅号,方法看下面的链接 https://blog.csdn.net/weixin_38007185/article/details/108245766?ops_request_mis ...

  8. 【瑞吉外卖】学习笔记-day5:(三)手机验证码登录(用邮件发送代替)

    短信发送: 短信服务介绍 目前市面上有很多第三方提供的短信服务,这些第三方短信服务会和各个运营商(移动.联通.电信)对接,我们只需要注册成为会员并且按照提供的开发文档进行调用就可以发送短信.需要说明的 ...

  9. java 瑞吉外卖 day5 套餐管理业务 套餐新增,套餐分页查询 套餐修改 套餐停售起售设置 短信服务

    新增套餐 准备工作: 套餐信息分页查询 前面已经写了好几个分页查询了,这里查询的关键点,是套餐分类名称,不在套餐表中,我们要到别的表里拿,然后封装进setmealDto @GetMapping(&qu ...

最新文章

  1. win10商店打不开_科技资讯:Win10系统电脑的应用商店老是打不开还闪退怎么办
  2. Reddit欲融资3亿美元,由腾讯领投
  3. hdu- 5015 233 Matrix
  4. objc_setAssociatedObject 关联的简单用法
  5. highcharts 怎么去掉鼠标悬停效果_练瑜伽减肥没效果什么原因?
  6. vector源码剖析
  7. Python自学之路NO.1-Python的安装与配置
  8. 实用调试技巧 Debug Release F10 F11 初始化 越界访问 堆栈 模拟实现库函数
  9. 支付签约_已成燎原之势!蜻蜓支付出库、签约、地推火爆!
  10. Android UI设计之十一自定义ViewGroup,打造通用的关闭键盘小控件ImeObser
  11. HTML image button
  12. 代理 傲澜智伴机器人_机器人厂家_智伴机器人代理,莆田智伴机器人,傲澜智伴机器人(查看)_一呼百应网...
  13. pythonjam教程_colorama(pythonjam官网)
  14. MapGISK9安装
  15. 2022年伊始,IT圈还有这些事是你不知道的?
  16. 嵌入式系统架构设计师的理解
  17. aris系统流程图意思与或非_流程管理
  18. 小区市话配套和宽带接入系统研究报告
  19. 修改 Mixamo 导出的动画名字
  20. Xposed模块开发

热门文章

  1. 大家尽管鄙视这种人吧!
  2. Linux 创建记事本和文件夹的命令
  3. JavaScript处理颜色常用方法
  4. js中15位及18位身份证号码的校验
  5. 工模插拔耳机电流声问题修改
  6. crosswalk源码 的编译过程
  7. 选择可解释性高的机器学习模型,而不是决策风险高的黑匣子模型
  8. 6月26日第壹简报,星期日,农历五月廿八
  9. Spring笔记9--Spring的三大重要配置(alias,bean,import)
  10. 趣头条四季度净亏损超预期 盘后暴跌逾14%