security实现手机验证码登陆

本文介绍了使用Spring Security实现手机验证码登录的过程。首先,用户输入手机号获取验证码,系统生成随机验证码存储在缓存中并发送给用户。接着,用户输入验证码后与缓存中的验证码进行比对。验证通过后,查找对应手机号的用户,并生成用户令牌,从而完成登录验证。前端接收到成功消息后直接跳转至首页,实现短信验证码登录功能。

项目用的是security来做安全校验,表单验证的就不谈了,现在讲一下我用手机验证码登陆的思路及实现方式。

手机验证码登陆的思路如下:

1、用户输入手机号,点击获取验证码

2、系统生成随机验证码,保存到缓存中,同时给用户下发验证码信息。

3、用户输入验证码后,和缓存中进行比对。

4、如果验证码正确,查出手机对应的用户。

5、根据查出来的用户,生成用户令牌,完成验证。(我主要就讲这里,其它步骤并不是重点,直接上代码)

@RequestMapping("/ajaxLogin")
	@ResponseBody
	public BaseResult<T> ajaxLogin(@RequestBody String json) {
		log.info("json============="+json);
		//校验验证码
		String checkrs=userRemote.checkCheckCode(json);
		log.info("checkrs============="+checkrs);
		
		if(checkrs.equals("error")) {
			//如果校验失败,返回错误信息
			return new BaseResult<>("001","验证码校验错误");
		}
		
		//如果校验正确,根据手机号查出用户信息
		JSONObject object=JSONObject.parseObject(json);
		String phone=object.getString("phone");
		
		String userrString=userRemote.getUserInfoByPhone(phone);
		log.info("userrString============="+userrString);
		if(StringUtils.isBlank(userrString)) {
			return new BaseResult<>("001","手机号未注册或未绑定用户");
		}
		
		JSONObject 
### Spring Security中集成短信验证码登录 #### 1. 自定义认证过滤器 为了实现基于短信验证码登录,在Spring Security框架内需创建一个自定义的`UsernamePasswordAuthenticationFilter`子类,用于拦截并处理携带手机号码和验证码的请求。此过程涉及到解析HTTP请求中的参数,并调用相应的身份验证机制[^1]。 ```java public class SmsCodeAuthenticationFilter extends AbstractAuthenticationProcessingFilter { public static final String SMS_CODE_PARAM = "smsCode"; private SessionStrategy sessionStrategy = new HttpSessionSessionStrategy(); protected SmsCodeAuthenticationFilter(String defaultFilterProcessesUrl) { super(defaultFilterProcessesUrl); } @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException { // 获取前端传递过来的数据 String mobile = obtainMobile(request); String smsCode = obtainSmsCode(request); if (StringUtils.isEmpty(mobile)) { throw new AuthenticationServiceException("手机号不能为空"); } if (StringUtils.isEmpty(smsCode)) { throw new AuthenticationServiceException("验证码不能为空"); } SmsCodeAuthenticationToken authRequest = new SmsCodeAuthenticationToken(mobile, smsCode); setDetails(request, authRequest); return this.getAuthenticationManager().authenticate(authRequest); } /** * 设置额外的信息到authentication对象里去. */ protected void setDetails(HttpServletRequest request, SmsCodeAuthenticationToken authRequest) { authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request)); } } ``` #### 2. 创建新的认证令牌类型 除了标准的身份验证令牌外,还需要定义一个新的`SmsCodeAuthenticationToken`类继承自`AbstractAuthenticationToken`,用来封装来自用户的输入——即手机号与验证码组合而成的凭证信息。 ```java 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; } ... } ``` #### 3. 构建自定义认证提供者 接着应该构建专门针对此类场景设计的`AuthenticationProvider`实例,负责实际执行对传入数据的有效性校验工作,比如检查数据库记录是否存在该电话号码以及其关联的状态是否有效;同时还要核对该次提交的一次性密码是否正确无误[^3]。 ```java @Component public class SmsCodeAuthenticationProvider implements AuthenticationProvider { @Autowired private UserService userService; @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { SmsCodeAuthenticationToken authenticationToken = (SmsCodeAuthenticationToken) authentication; String mobile = (String) authenticationToken.getPrincipal(); String code = (String) authenticationToken.getCredentials(); User user = userService.findByMobile(mobile); if(user == null){ throw new BadCredentialsException("用户不存在!"); }else{ boolean isValidated = validateSmsCode(code,user.getId()); if(!isValidated){ throw new BadCredentialsException("验证码错误!"); } Collection<? extends GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER"); return new UsernamePasswordAuthenticationToken(new AuthUserDetail(user),null ,authorities ); } } private Boolean validateSmsCode(String inputCode,Long userId){ // 这里可以加入自己的业务逻辑判断验证码有效性... return true; } @Override public boolean supports(Class<?> aClass) { return SmsCodeAuthenticationToken.class.isAssignableFrom(aClass); } } ``` #### 4. 注册组件至Security配置文件 最后一步是在应用程序的安全设置中注册上述开发出来的各个部分,确保它们能够被正常加载并参与到整个安全体系当中发挥作用。这通常意味着修改现有的WebSecurityConfigurerAdapter派生类或者采用更现代的方式来完成相同的目标[^2]。 ```java @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private SmsCodeAuthenticationProvider smsCodeAuthProvider; @Bean public SmsCodeAuthenticationFilter smsCodeAuthFilter() throws Exception { SmsCodeAuthenticationFilter filter = new SmsCodeAuthenticationFilter("/login/mobile"); filter.setAuthenticationSuccessHandler(...); filter.setAuthenticationFailureHandler(...); filter.setAuthenticationManager(authenticationManagerBean()); return filter; } @Override protected void configure(HttpSecurity http) throws Exception { http.addFilterBefore(smsCodeAuthFilter(), UsernamePasswordAuthenticationFilter.class).authorizeRequests() .antMatchers("/login/**").permitAll() .anyRequest().authenticated(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.authenticationProvider(smsCodeAuthProvider); } } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值