文章目录
项目源码地址 https://github.com/nieandsun/security
1. 内容简介
有些系统进行用户认证可能是校验短信验证码,而不是使用用户名和密码。
spring-security并没有实现一套关于短信验证码的校验逻辑,但是我们可以仿照用户名+密码的校验方式来自己写Filter,然后将自己写的Filter加入到spring-security的过滤器链中来实现利用短信进行认证的功能。
由于短信验证码与前面文章中介绍的图形验证码之间会存在一些耦合且短信验证码功能的开发相交于以往会更繁琐一些,因此为了能更好地表达明白这块的具体工作内容,我会将其分成几篇博客来进行一一介绍。
本篇文章主要介绍获取短信验证码接口的开发,即用户向后端传一个手机号,后端生成一个随机数,归结起来其主要步骤如下:
- 用户前端传一个手机号给后端
- 后端获得手机号 – > 生成一个随机的验证码 – > 将生成的验证码写入session – > 将生成的验证码通过手机号发给用户
2. 具体代码开发
2.1 短信验证码登陆认证页面开发
注意: 这里手机号不是真正的手机号,后端也不会真正的调用手机发送验证码的服务,主要是学习整个流程!!!
<h3>短信登录</h3>
<form action="/authentication/mobile" method="post">
<table>
<tr>
<td>手机号:</td>
<td><input type="text" name="mobile" value="13012345678"></td>
</tr>
<tr>
<td>短信验证码:</td>
<td>
<input type="text" name="smsCode">
<a href="/code/sms?mobile=13012345678">发送验证码</a>
</td>
</tr>
<tr>
<td colspan="2">
<button type="submit">登录</button>
</td>
</tr>
</table>
</form>
2.2 获取短信验证码接口开发
2.2.1 获取短信验证码接口—总
/**
* 生成短信验证码
*
* @param request
* @param response
*/
@GetMapping("/code/sms")
public void createSmsCode(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletRequestBindingException {
//1.获取传过来的电话号码
String mobile = ServletRequestUtils.getRequiredStringParameter(request, "mobile");
//2.生成SmsCode对象
ValidateCode smsCode = smsCodeGenerator.generate(new ServletWebRequest(request));
//3.将ImageCode对象写入到session
sessionStrategy.setAttribute(new ServletWebRequest(request), SESSION_KEY, smsCode);
//4.将生成的验证码通过手机号发给用户
smsCodeSender.send(mobile, smsCode.getCode());
}
2.2.2 生成SmsCode对象—分
package com.nrsc.security.core.validate.code;
import com.nrsc.security.core.properties.SecurityProperties;
import org.apache.commons.lang.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.ServletWebRequest;
/**
* @author: Sun Chuan
* @date: 2019/7/9 12:29
* @Description: 注意验证码+ 超时时间可以进行配置
*/
@Component("smsCodeGenerator")
public class SmsCodeGenerator implements ValidateCodeGenerator {
@Autowired
private SecurityProperties securityProperties;
@Override
public ValidateCode generate(ServletWebRequest request) {
String code = RandomStringUtils.randomNumeric(securityProperties.getCode().getSms().getLength());
return new ValidateCode(code, securityProperties.getCode().getSms().getExpireIn());
}
}
2.2.3 将生成的验证码通过手机号发给用户— 开发者应implements 发短信接口然后自己去完成具体实现—分
package com.nrsc.security.core.validate.code.sms;
/**
* @author: Sun Chuan
* @date: 2019/7/9 19:48
* Description: 注意SmsCodeSender为定义的“将生成的验证码通过手机号发给用户”的接口
* 开发者应该继承该接口,然后根据具体供应商即联通、移动、电信等完成发送短信功能的具体实现,
* 而本类为一个超级简单的实现,并没有向用户发送短信功能,只是向控制台输出一句话
*/
public class DefaultSmsCodeSender implements SmsCodeSender {
@Override
public void send(String mobile, String code) {
System.out.println("向手机" + mobile + "发送短信验证码" + code);
}
}
在配配置类中注明,当spring容器中找到SmsCodeSender的其他实现类时,会覆盖我们写的DefaultSmsCodeSender
@Bean
@ConditionalOnMissingBean(SmsCodeSender.class)
public SmsCodeSender smsCodeSender() {
return new DefaultSmsCodeSender();
}
2.3 在配置文件里指定不拦截获取短信验证码的接口
.antMatchers("/code/*", "/authentication/require", securityProperties.getBrowser().getLoginPage())//指定不校验的url
.permitAll()
2.4 代码重构— 请看github上的本次提交
本篇文章的代码重构都比较琐碎,且没有太多高超的技巧,我会统一提交到我的github上,代码地址https://github.com/nieandsun/security,想看的可以通过git的commitID查看我的本次提交,看到所有的代码改动!
新建+修改的所有文件如下: