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/19 12:36:26 阅读更多 →
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/19 12:35:25 阅读更多 →
数据可观测性:现代数据架构的核心支柱

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

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

2026/7/19 12:35:25 阅读更多 →

最新新闻

Windows免安装版MySQL8详细安装配置教程(ZIP 压缩包版)

Windows免安装版MySQL8详细安装配置教程(ZIP 压缩包版)

1 前言很多小伙伴在安装MySQL时,习惯去找MSI安装包一路“下一步”,但这种方式会在系统里写入大量注册表信息,卸载不干净时还容易留下各种残留,导致重装失败。其实MySQL官方一直提供ZIP压缩包版(也叫noinstall ZIP Arch…

2026/7/19 18:27:07 阅读更多 →
atom-in-orbit调试技巧:在浏览器中调试Atom的完整方法

atom-in-orbit调试技巧:在浏览器中调试Atom的完整方法

atom-in-orbit调试技巧:在浏览器中调试Atom的完整方法 【免费下载链接】atom-in-orbit Putting Atom in the browser 项目地址: https://gitcode.com/gh_mirrors/at/atom-in-orbit 想要在浏览器中运行和调试Atom编辑器吗?atom-in-orbit项目为您提…

2026/7/19 18:27:07 阅读更多 →
官宣|AT Work 正式开源,中小团队免费部署的一站式云研发工作台

官宣|AT Work 正式开源,中小团队免费部署的一站式云研发工作台

中小研发团队的日常,大概率是这样的: 需求写在 Jira 或飞书多维表里,代码在 GitLab,文档散落在语雀和腾讯文档,文件靠微信传来传去,沟通靠企业微信或钉钉——每天在 5 款以上工具之间来回切换,…

2026/7/19 18:27:07 阅读更多 →
你的Discord表情包太单调?试试这款Project Sekai贴纸生成器!

你的Discord表情包太单调?试试这款Project Sekai贴纸生成器!

你的Discord表情包太单调?试试这款Project Sekai贴纸生成器! 【免费下载链接】sekai-stickers Project Sekai sticker maker 项目地址: https://gitcode.com/gh_mirrors/se/sekai-stickers 你是否在Discord聊天中总是使用同样的表情包&#xff0c…

2026/7/19 18:27:07 阅读更多 →
冒泡排序与选择排序完整对比解析

冒泡排序与选择排序完整对比解析

一、两种排序底层逻辑差异1. 冒泡排序(课件抱西瓜案例)生活比喻:每层电梯口放西瓜,每次只抱一个,上楼途中遇到更大西瓜就交换,一趟走完,最大西瓜会落到最末尾。默认排序:从小到大升序…

2026/7/19 18:27:07 阅读更多 →
7个理由告诉你为什么OpenBoard是安卓用户必备的隐私保护键盘

7个理由告诉你为什么OpenBoard是安卓用户必备的隐私保护键盘

7个理由告诉你为什么OpenBoard是安卓用户必备的隐私保护键盘 【免费下载链接】openboard 项目地址: https://gitcode.com/gh_mirrors/op/openboard 在数字时代,您的每一次按键都可能被监控和收集。OpenBoard作为一款100%开源键盘应用,为您提供了…

2026/7/19 18:26:07 阅读更多 →

日新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/19 0:00:40 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/19 0:00:40 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/19 0:00:40 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/19 0:00:40 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/19 0:00:40 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/19 0:00:40 阅读更多 →

月新闻