Spring Security集成手机验证码登录实战指南
1. 项目概述在当今移动互联网时代手机验证码登录已成为各类应用的标准配置。作为一名长期使用Spring Security的开发者我发现很多团队在集成手机验证码登录时都会遇到各种坑——要么是验证流程设计不合理要么是与Spring Security原有体系融合不彻底。今天我就来分享一个经过多个生产项目验证的解决方案让你在5分钟内快速实现这一功能。这个方案的核心在于理解Spring Security的认证流程扩展点。不同于传统的用户名密码认证手机验证码登录需要自定义三个关键组件验证码生成与校验过滤器Filter、验证码认证令牌Token以及对应的认证提供者Provider。下面我会详细拆解每个环节的实现要点。2. 核心组件设计与实现2.1 验证码过滤器设计首先需要创建一个继承自OncePerRequestFilter的验证码过滤器。这个过滤器需要完成以下工作public class SmsCodeFilter extends OncePerRequestFilter { private static final String SMS_LOGIN_URL /login/mobile; Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { if (SMS_LOGIN_URL.equals(request.getRequestURI()) POST.equalsIgnoreCase(request.getMethod())) { try { validateCode(request); } catch (AuthenticationException e) { unsuccessfulAuthentication(request, response, e); return; } } filterChain.doFilter(request, response); } private void validateCode(HttpServletRequest request) { String mobile request.getParameter(mobile); String code request.getParameter(code); // 实际项目中这里应该调用验证码服务校验 if (!123456.equals(code)) { // 示例代码生产环境需要替换 throw new BadCredentialsException(验证码错误); } } private void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException { SecurityContextHolder.clearContext(); response.sendError(HttpServletResponse.SC_UNAUTHORIZED, failed.getMessage()); } }关键点过滤器应该只拦截特定的验证码登录URL避免影响其他认证流程。验证失败时需要清除SecurityContext并返回401状态码。2.2 认证令牌与认证提供者接下来需要创建自定义的认证令牌和提供者public class SmsCodeAuthenticationToken extends AbstractAuthenticationToken { private final Object principal; // 这里存储手机号 private Object credentials; // 这里存储验证码 public SmsCodeAuthenticationToken(Object principal, Object credentials) { super(null); this.principal principal; this.credentials credentials; setAuthenticated(false); } // 实现父类抽象方法 Override public Object getCredentials() { return this.credentials; } Override public Object getPrincipal() { return this.principal; } } Service public class SmsCodeAuthenticationProvider implements AuthenticationProvider { Autowired private UserDetailsService userDetailsService; Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { SmsCodeAuthenticationToken authenticationToken (SmsCodeAuthenticationToken) authentication; String mobile (String) authenticationToken.getPrincipal(); UserDetails user userDetailsService.loadUserByUsername(mobile); if (user null) { throw new UsernameNotFoundException(手机号未注册); } SmsCodeAuthenticationToken result new SmsCodeAuthenticationToken( user, null, user.getAuthorities()); result.setDetails(authenticationToken.getDetails()); return result; } Override public boolean supports(Class? authentication) { return SmsCodeAuthenticationToken.class.isAssignableFrom(authentication); } }注意认证提供者中我们只验证用户是否存在因为验证码已经在过滤器中校验过了。这是职责分离的重要设计。3. Spring Security配置集成3.1 安全配置类将上述组件集成到Spring Security配置中Configuration EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { Autowired private SmsCodeAuthenticationProvider smsCodeAuthenticationProvider; Override protected void configure(HttpSecurity http) throws Exception { http.addFilterBefore(smsCodeFilter(), UsernamePasswordAuthenticationFilter.class) .authorizeRequests() .antMatchers(/code/sms).permitAll() .anyRequest().authenticated() .and() .formLogin() .loginPage(/login) .loginProcessingUrl(/login/form) .defaultSuccessUrl(/) .and() .logout() .logoutUrl(/logout) .logoutSuccessUrl(/login); } Bean public SmsCodeFilter smsCodeFilter() { return new SmsCodeFilter(); } Override protected void configure(AuthenticationManagerBuilder auth) { auth.authenticationProvider(smsCodeAuthenticationProvider); } }3.2 验证码发送接口虽然不属于Spring Security核心流程但验证码发送是完整功能的一部分RestController public class SmsCodeController { GetMapping(/code/sms) public Result sendSmsCode(RequestParam String mobile) { // 实际项目中这里应该调用短信服务发送验证码 String code generateRandomCode(); // 将验证码存入缓存设置5分钟过期 redisTemplate.opsForValue().set(sms_code: mobile, code, 5, TimeUnit.MINUTES); return Result.success(验证码已发送); } private String generateRandomCode() { return String.valueOf(new Random().nextInt(899999) 100000); } }4. 前端对接与测试4.1 前端登录表单手机验证码登录需要特定的表单form action/login/mobile methodpost input typetext namemobile placeholder手机号 input typetext namecode placeholder验证码 button typebutton onclicksendCode()获取验证码/button button typesubmit登录/button /form script function sendCode() { const mobile document.querySelector(input[namemobile]).value; fetch(/code/sms?mobile mobile) .then(response response.json()) .then(data alert(data.message)); } /script4.2 测试要点测试时需要关注以下几个关键点验证码有效期验证5分钟后应该失效同一手机号验证码防重放攻击验证码错误次数限制与原有表单登录的兼容性5. 生产环境注意事项在实际项目中还需要考虑以下问题验证码安全验证码长度建议6位包含数字即可设置合理的发送频率限制如60秒内只能发送一次同一IP/设备发送次数限制性能优化验证码校验使用Redis等内存数据库考虑使用本地缓存减少Redis访问异常处理短信服务不可用时的降级方案验证码输入错误时的友好提示日志记录记录验证码发送和验证日志关键操作需要审计日志我在实际项目中遇到过的一个典型问题当系统同时存在表单登录和验证码登录时如果用户先尝试表单登录失败再尝试验证码登录有时会出现认证状态混乱。解决方案是在过滤器中明确区分两种认证流程确保它们互不干扰。

相关新闻

EmuDeck终极指南:一键配置Steam Deck模拟器的完整解决方案

EmuDeck终极指南:一键配置Steam Deck模拟器的完整解决方案

EmuDeck终极指南:一键配置Steam Deck模拟器的完整解决方案 【免费下载链接】EmuDeck Emulator configurator for Steam Deck 项目地址: https://gitcode.com/gh_mirrors/em/EmuDeck EmuDeck是专为Steam Deck设计的模拟器自动配置工具,通过一键安装…

2026/7/29 22:52:28 阅读更多 →
SVGcode终极指南:3分钟将位图转为可无限放大的矢量图

SVGcode终极指南:3分钟将位图转为可无限放大的矢量图

SVGcode终极指南:3分钟将位图转为可无限放大的矢量图 【免费下载链接】SVGcode Convert color bitmap images to color SVG vector images. 项目地址: https://gitcode.com/gh_mirrors/sv/SVGcode 你是否曾为放大Logo时出现的模糊边缘而烦恼?或者…

2026/7/29 4:26:41 阅读更多 →
数据可观测性:现代数据架构的核心支柱

数据可观测性:现代数据架构的核心支柱

1. 数据可观测性的本质与价值 数据可观测性(Data Observability)正在成为现代数据架构的核心支柱。与传统的监控(Monitoring)不同,可观测性强调的是通过系统输出的外部特征来推断内部状态的能力。就像医生通过体温、血…

2026/7/28 9:28:06 阅读更多 →

最新新闻

负温度下湿度换算:从Goff-Gratch公式到工程实践

负温度下湿度换算:从Goff-Gratch公式到工程实践

1. 项目缘起:一个被忽视的“负温度”需求最近在做一个环境监控相关的项目,需要处理大量的温湿度传感器数据。在数据校准和跨系统对接时,不可避免地要面对一个基础但关键的问题:相对湿度与绝对湿度的换算。这听起来像是气象学或暖通…

2026/7/30 12:30:55 阅读更多 →
AI代码生成中的加密模式选择:CBC、ECB、CTR对比与实战避坑指南

AI代码生成中的加密模式选择:CBC、ECB、CTR对比与实战避坑指南

1. 项目概述:当AI开始写加密代码,模式选择成了新难题 最近在几个AI辅助开发的社群里,看到不少朋友在讨论一个挺有意思的问题:让AI助手帮忙生成加密解密的代码片段时,结果常常五花八门。有的直接甩给你一段AES-CBC的代码…

2026/7/30 12:30:55 阅读更多 →
舵机驱动全解析:从PWM原理到STM32/Arduino实战应用

舵机驱动全解析:从PWM原理到STM32/Arduino实战应用

1. 从“会动的关节”说起:舵机到底是什么? 如果你玩过遥控车、航模,或者拆解过一些智能玩具,大概率见过一个方方正正、带着三根线(红、棕/黑、黄/白/橙)的小盒子。给它通电,它就能带着一个“手臂…

2026/7/30 12:30:55 阅读更多 →
模型参考自适应控制(MRAC)原理与MATLAB仿真:从理论到实践

模型参考自适应控制(MRAC)原理与MATLAB仿真:从理论到实践

1. 从“暴力枚举”到“智能适应”:为什么我们需要自适应控制? 如果你做过嵌入式开发,比如用STM32控制一个电机,或者用Arduino驱动一个小车,大概率遇到过这样的场景:你精心设计了一套PID参数,在实…

2026/7/30 12:30:55 阅读更多 →
企业AI Agent如何真正接入业务流程?从MCP、A2A到BPMN的流程编排架构

企业AI Agent如何真正接入业务流程?从MCP、A2A到BPMN的流程编排架构

随着大模型从智能问答走向任务执行,AI Agent正在进入采购、合同、财务、质量、客服和供应链等企业场景。它可以理解需求、查询数据、调用工具,甚至与其他Agent协同完成任务。 但能够调用几个接口,并不等于能够独立处理一项企业业务。 企业流…

2026/7/30 12:30:55 阅读更多 →
大模型应用开发火爆!1-3年经验月薪30-50K,零基础也能冲高薪!

大模型应用开发火爆!1-3年经验月薪30-50K,零基础也能冲高薪!

大模型应用开发值不值得冲?现在还来得及吗? 中国人工智能学会2025年度报告显示,国内大模型核心领域人才总缺口达120万,其中应用开发岗占比超60%。 与此同时,据新东方网2026年4月报道,AI应用开发工程师1-3年…

2026/7/30 12:29:55 阅读更多 →

日新闻

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南 【免费下载链接】DriverStoreExplorer Driver Store Explorer 项目地址: https://gitcode.com/gh_mirrors/dr/DriverStoreExplorer 您是否曾因Windows系统盘空间不足而烦恼?是否遇到过设…

2026/7/30 0:00:13 阅读更多 →
如何3步掌握Video Download Helper:网页视频下载的完整实战指南

如何3步掌握Video Download Helper:网页视频下载的完整实战指南

如何3步掌握Video Download Helper:网页视频下载的完整实战指南 【免费下载链接】VideoDownloadHelper Chrome Extension to Help Download Video for Some Video Sites. 项目地址: https://gitcode.com/gh_mirrors/vi/VideoDownloadHelper 你是否曾经在浏览…

2026/7/30 0:00:13 阅读更多 →
“双减”后首个AI备课压力测试报告:覆盖32所中小学的176节AI辅助课,暴露4大隐性增负节点

“双减”后首个AI备课压力测试报告:覆盖32所中小学的176节AI辅助课,暴露4大隐性增负节点

更多请点击: https://intelliparadigm.com 第一章:AI 教师备课辅助 AI 教师备课辅助系统正逐步成为教育数字化转型的核心支撑工具,它并非替代教师,而是通过语义理解、知识图谱与多模态生成能力,将教师从重复性劳动中解…

2026/7/30 0:00:13 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/29 22:18:20 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/29 14:34:28 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/29 15:00:03 阅读更多 →

月新闻