从零用java实现 小红书 springboot vue uniapp(14) 集成阿里云短信验证码

移动端演示 http://8.146.211.120:8081/#/

管理端演示 http://8.146.211.120:8088/#/

项目整体介绍及演示

前言

在现代应用中,手机号不仅是用户的唯一标识,更是保障账户安全的第一道防线。通过短信验证码进行登录或注册,已成为行业标准。它省去了用户记忆复杂密码的麻烦,同时提供了可靠的身份验证。在本文中,我们将为我们的小红书项目集成阿里云短信服务,实现一个完整、安全、且对开发者友好的手机验证码登录流程。


在这里插入图片描述

核心技术实现

整个流程分为后端和前端两部分。后端负责生成验证码、调用阿里云接口发送短信、以及校验验证码的有效性。前端则负责提供用户界面,引导用户输入手机号并完成验证。

1. 后端实现:从配置到接口
步骤一:引入阿里云SDK依赖

首先,我们需要在项目的 pom.xml 中加入阿里云短信服务的Java SDK。

<dependency><groupId>com.aliyun</groupId><artifactId>dysmsapi20170525</artifactId><version>2.0.24</version> <!-- 请使用最新版本 -->
</dependency>
步骤二:参数化配置

为了代码的灵活性和安全性,我们将所有敏感信息和配置项都放入 application.yml 中。这样做的好处是,我们可以在不同环境(开发、测试、生产)中使用不同的配置,而无需修改代码。

# 阿里云短信服务
aliyun:sms:# 是否启用真实短信发送, false则为测试模式enabled: false # 阿里云账号的accessKeyIdaccess-key-id: YOUR_ACCESS_KEY_ID# 阿里云账号的accessKeySecretaccess-key-secret: YOUR_ACCESS_KEY_SECRET# 短信签名名称 (需在阿里云控制台申请)sign-name: 你的签名# 短信模板CODE (需在阿里云控制台申请)template-code: SMS_XXXXXX# 短信验证码有效期(分钟)expire-minutes: 1
  • enabled: 这是一个非常有用的开关。当设为 false 时,系统进入“测试模式”,验证码会直接在接口中返回,而不会真实发送,方便开发调试。
  • access-key-id & access-key-secret: 你的阿里云账户凭证。
  • sign-name & template-code: 在阿里云短信服务控制台创建的短信签名和模板。
步骤三:封装短信发送服务

接下来,我们创建一个 SmsServiceImpl,它将负责所有与发送短信相关的逻辑。这种封装能让我们的业务代码(如登录逻辑)保持干净,只需调用一个简单的方法即可。

SmsServiceImpl.java:

@Slf4j
@Service
public class SmsServiceImpl implements SmsService {@Autowiredprivate SmsProperties smsProperties;@Autowiredprivate AliyunSmsConfig aliyunSmsConfig;@Autowiredprivate SystemSettingService systemSettingService; // 用于获取系统设置@Overridepublic void sendMessage(String phoneNumber, String code) throws Exception {// 从系统设置或配置中获取当前的模式// String smsMode = systemSettingService.getSmsMode();// 此处我们直接使用yml中的配置boolean isRealMode = smsProperties.isEnabled();if (!isRealMode) {// 测试模式:只记录日志,不真实发送log.info("【测试模式】短信发送 - 手机号: {}, 验证码: {}", phoneNumber, code);return;}try {log.info("【真实模式】开始发送短信 - 手机号: {}, 验证码: {}", phoneNumber, code);Client client = aliyunSmsConfig.createClient();Map<String, String> templateParamMap = new HashMap<>();templateParamMap.put("code", code); // 模板参数,key必须与模板中的变量名一致String templateParam = JSON.toJSONString(templateParamMap);SendSmsRequest sendSmsRequest = new SendSmsRequest().setPhoneNumbers(phoneNumber).setSignName(smsProperties.getSignName()).setTemplateCode(smsProperties.getTemplateCode()).setTemplateParam(templateParam);RuntimeOptions runtime = new RuntimeOptions();SendSmsResponse sendSmsResponse = client.sendSmsWithOptions(sendSmsRequest, runtime);log.info("短信发送结果: {}", sendSmsResponse.getBody().getMessage());if (sendSmsResponse.getBody() == null || !"OK".equals(sendSmsResponse.getBody().getCode())) {throw new ApiException("短信发送失败: " + (sendSmsResponse.getBody() != null ? sendSmsResponse.getBody().getMessage() : "未知错误"));}} catch (Exception e) {log.error("短信发送异常", e);throw new ApiException("短信发送异常: " + e.getMessage());}}
}

该服务通过检查 aliyun.sms.enabled 的值来决定是打印日志(测试模式)还是调用阿里云API(真实模式)。

步骤四:创建登录接口

最后,我们在 LoginApi 中创建两个端点:一个用于获取验证码,另一个用于通过验证码登录。

LoginApi.java:

@RestController
public class LoginApi {@AutowiredLoginService loginService;@AutowiredAuthorService authorService;@Autowiredprivate JwtTokenUtil jwtTokenUtil;@ApiOperation(value = "获取验证码")@GetMapping("/api/getCode")public ResultBean<String> getCode(String phoneNumber) {// loginService 内部会生成验证码、存入Redis、并调用SmsService发送String code = loginService.sendSmsCode(phoneNumber);if (code == null) {// 真实模式下,service层返回null,提示用户return ResultBean.success("验证码已发送,请注意查收");}// 测试模式下,service层返回验证码,直接显示给前端return ResultBean.success(code);}@ApiOperation(value = "验证码登陆")@PostMapping("/api/checkCode")@Transactionalpublic ResultBean<Author> checkCode(@RequestBody PhoneLoginDto phoneLoginDto) {// 1. 校验验证码是否正确 (loginService会去Redis中比对)loginService.checkCode(phoneLoginDto);// 2. 验证通过,执行登录或注册逻辑Author author = authorService.selectAuthorByPhoneNumber(phoneLoginDto.getPhoneNumber());if(author == null){// 用户不存在,创建新用户author = authorService.createNewAuthor(phoneLoginDto.getPhoneNumber());} else if(author.getDeleted().equals(1)){throw new ApiException("当前用户状态异常~");}// 3. 生成Token并返回用户信息final String token = jwtTokenUtil.generateTokenByUserId(author.getAuthorId());author.setToken(token);return ResultBean.success(author);}
}
  • /api/getCode: 这个接口的设计完美地结合了测试与真实模式。在开发阶段,我们能立刻看到验证码,极大提高了调试效率。
  • /api/checkCode: 它首先验证验证码的正确性,然后执行“查找或创建”用户的逻辑,最后签发JWT令牌,完成整个登录闭环。
    主要逻辑是将验证码保存到redis 设置过期时间 到期重新发送 根据输入的值和redis数据库比较

2. 前端交互:Uniapp 实现

前端的实现相对直接,主要是在登录页面 login.vue 中完成。
在这里插入图片描述

  1. UI布局: 包含一个手机号输入框、一个“获取验证码”按钮和一个“登录”按钮。
  2. 获取验证码:
    • 点击“获取验证码”按钮时,调用后端的 /api/getCode 接口。
    • 接口调用成功后,启动一个60秒的倒计时,期间按钮变为不可点击状态,防止用户重复发送。
  3. 登录:
    • 用户输入手机号和收到的验证码后,点击“登录”按钮。
    • 调用后端的 /api/checkCode 接口,并传递手机号和验证码。
    • 登录成功后,后端会返回用户信息和Token。前端需要将这些信息(特别是Token)保存到本地存储(如 uni.setStorageSync),并跳转到应用主页。

通过前后端的紧密配合,我们就构建了一个完整且健壮的短信验证码登录功能。

代码地址
https://gitee.com/ddeatrr/springboot_vue_xhs

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

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

相关文章

`<< EOF` 与 `<< ‘EOF‘` 与 `<< “EOF“`有无引号的区别多回答笔记250722

<< EOF 与 << EOF 与 << "EOF"有无引号的区别多回答笔记250722 实测 自测代码: # 定义变量 hello"ni hao"# 无引号 tee << EOF # 无引号 ${hello} world \n $(date) # 无引号 EOF# 单引号 tee << EOF # 单…

点击按钮滚动到底功能vue的v-on:scroll运用

使用vue自带的监听滚动功能v-on:scroll&#xff0c;滚动条变化时&#xff0c;会调用方法 checkScrollStatus&#xff0c;如果滚动条在容器底部时&#xff0c;则隐藏按钮&#xff0c;否则显示按钮&#xff0c;点击按钮能一键滚动到底部。<div class"chat-area" ref…

Linux下编译SLEPc

本文记录在Linux下编译安装SLEPc的流程。 一、下载代码 git clone https://github.com/slepc/slepc.git cd ./slepc二、安装依赖 2.1 安装PETSc 参见: <Linux下编译安装PETSc> 2.2 安装intel oneAPI sudo apt install intel-oneapi-base-toolkit sudo apt install i…

【无标题】qwen3-8b 强化学习训练后的模型,可以接着 进行其他grpo 强化学习训练 吗

ser_count’, 0),)} {((‘valid_user_count’, 1),)} 44 0.0 88 [0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.0, 0.6, 0.0, 0.6, 0.0, 0.6] 55 100%|???{‘loss’: 0.0132, ‘grad_norm’: 0.07552657276391983, ‘learning_rate’: 2e-06, ‘num_tokens’: 2098…

IDC权威认可:瑞数信息双项入选《中国大模型安全保护市场概览》

近日&#xff0c;国际数据公司IDC正式发布了《中国大模型安全保护市场概览&#xff0c;2025&#xff1a;全方位安全检测与防护构建可信AI》报告。本次报告中IDC结合全球统一定义以及中国市场特色&#xff0c;将中国大模型安全保护市场划分为7个细分领域&#xff0c;并通过对中国…

多智能体(Multi-agent)策略模式:思维链CoT和ReAct

参考&#xff1a;https://zhuanlan.zhihu.com/p/704523060 &#x1f3af; 一句话记住 CoT&#xff1a;像“考试时在草稿纸上写完所有步骤&#xff0c;再抄答案”。ReAct&#xff1a;像“玩密室逃脱&#xff0c;每开一个箱子就去找下一个线索”。 用小学生能听懂的话 两个小故事…

ChatGPT指令大全:输入需求=输出完整方案

ChatGPT指令大全提供数百个精炼过的指令语句 (提示词)&#xff0c;让你充分发挥 ChatGPT 的强大功能 一、核心功能模块分类 1. 求职与面试 简历优化 专业反馈&#xff1a;按面试官视角分析简历并提出改进建议量化数据&#xff1a;为经历添加具体数字&#xff08;如提升效率30…

Java零基础入门学习知识点2-JDK安装配置+Maven

文章目录版本提示参考视频Maven环境准备一、安装Java开发工具包&#xff08;JDK&#xff09;二、JDK环境配置三、下载Maven安装包*四、Maven环境配置&#xff08;可省略&#xff09;*五、验证安装&#xff08;上一步没做&#xff0c;这步无法验证&#xff0c;可省&#xff09;六…

基于单片机智能衣柜/智能衣橱设计

传送门 &#x1f449;&#x1f449;&#x1f449;&#x1f449;其他作品题目速选一览表 &#x1f449;&#x1f449;&#x1f449;&#x1f449;其他作品题目功能速览 概述 本设计实现了一种基于单片机的多功能智能衣柜&#xff0c;融合环境检测、安全防护与用户交互功能…

自动语音识别(ASR)技术详解

语音识别&#xff08;Automatic Speech Recognition, ASR&#xff09;是人工智能和自然语言处理领域的重要技术&#xff0c;旨在将人类的语音信号转换为对应的文本。近年来&#xff0c;深度学习的突破推动语音识别系统从实验室走入日常生活&#xff0c;为智能助手、实时翻译、医…

【MySQL】MySQL 事务和锁详解

一、MySQL 事务 1.1 事务介绍 在 MySQL 中&#xff0c;事务&#xff08;Transaction&#xff09; 是一组不可分割的 SQL 操作序列&#xff0c;这些操作要么全部成功执行&#xff0c;要么全部失败回滚&#xff0c;以此保证数据库操作的完整性和一致性。 事务将数据库从一种一致…

虚拟直线阈值告警人员计数算法暑期应用

智慧人员计数助力暑期&#xff1a;技术赋能安全管理的创新实践一、背景&#xff1a;暑期人流激增下的安全管理挑战暑期是旅游、商业、交通等场景的客流高峰期&#xff0c;人员密集区域易引发踩踏事故、管理混乱等安全隐患。传统人工计数方式效率低、误差大&#xff0c;难以满足…

SQL164 2021年11月每天新用户的次日留存率

SQL164 2021年11月每天新用户的次日留存率 思路 ​找出新用户​&#xff1a;确定每个用户首次活跃的日期&#xff08;即新用户&#xff09; 例如101用户在11月1日首次出现 ​处理跨天活跃​&#xff1a;考虑用户可能跨天活跃的情况&#xff08;in_time和out_time不在同一天&a…

基于单片机的数字电压表设计

2 系统原理及基本框图 如图2.1所示&#xff0c;模拟电压经过档位切换到不同的分压电路衰减后&#xff0c;经隔离干扰送到A/D转换器进行A/D转换&#xff0c;然后送到单片机中进行数据处理。处理后的数据送到LCD中显示&#xff0c;同时通过串行通讯与上位机通信。图2.1系统基本方…

[NLP]UPF基本语法及其在 native low power verification中的典型流程

UPF基本语法及其在 native low power verification中的典型流程 摘要:本文首先简要介绍 UPF(Unified Power Format),然后解释其在 native low power verification(原生低功耗验证)中的典型流程。最后,我将使用50个具体例子来完整展示 UPF 的关键语法。这些例子基…

fish-speech 在50系列显卡使用 --compile加速兼容

#环境说明 GPU: NVIDIA GeForce RTX 5080 Laptop GPU (sm_120) win11家庭版 24H2 #问题汇总 baize.exceptions.HTTPException: (500, "RuntimeError: ptxas failed with error code 4294967295: \\n\\n") 问题汇总 1 baize.exceptions.HTTPException: (500, "…

UI自动化测试实战

Python接口自动化测试零基础入门到精通&#xff08;2025最新版&#xff09;一、设计背景 随着IT行业的发展&#xff0c;产品愈渐复杂&#xff0c;web端业务及流程更加繁琐&#xff0c;目前UI测试仅是针对单一页面&#xff0c;操作量大。为了满足多页面功能及流程的需求及节省工…

面试实战,问题六,被问数据库索引,怎么回答

Java开发面试&#xff1a;数据库索引的原理及常见问题解答 在Java开发面试中&#xff0c;数据库索引是核心知识点&#xff0c;涉及数据库优化和性能调优。索引通过高效的数据结构加速数据检索&#xff0c;降低磁盘IO成本&#xff0c;并支持排序操作。下面我将逐步解释索引的原理…

ARM-I2C硬实现

硬件I2C-GD32F4系列的实现初始化操作在初始化函数里执行以下代码uint32_t i2cx_scl_port_rcu RCU_GPIOB; uint32_t i2cx_scl_port GPIOB; uint32_t i2cx_scl_pin GPIO_PIN_6; uint32_t i2cx_scl_af GPIO_AF_4;uint32_t i2cx_sda_port_rcu RCU_GPIOB; uint32_t i2cx_sda_po…

WinUI3开发_过渡动画

简介 过渡动画是当发生事件时控件UI状态发生改变时以一种动画形式来演变到另外一种状态&#xff0c;而非瞬间改变&#xff0c;使用一种更加平滑的方式来进行切换&#xff0c;例如下图是文字切换的交叉栅栏效果&#xff1a;还有页面切换动画&#xff1a;在或者是图标动画&#x…