实现短信验证码登录

  开发短信验证码接口

  校验短信验证码并登录

短信验证码和图片验证码开发思路类似:

1,我们访问一个controller

2,在controller里调用短信验证码生成接口生成验证码

3,验证码存进session

4,从请求里获取手机号,调用短信发送服务商的接口,给手机号发送短信

主要代码:

1,短信验证码Controller:

package com.imooc.security.core.validate.code;

import java.io.IOException;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.social.connect.web.HttpSessionSessionStrategy;
import org.springframework.social.connect.web.SessionStrategy;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.ServletWebRequest; import com.imooc.security.core.properties.SecurityProperties;
import com.imooc.security.core.validate.code.sms.SmsCodeSender; /**
* 验证码Control
* ClassName: ValidateCodeController
* @Description: TODO
* @author lihaoyang
* @date 2018年3月1日
*/
@RestController
public class ValidateCodeController { public static final String SESSION_KEY = "SESSION_KEY_IMAGE_CODE"; // @Autowired
// private SecurityProperties securityProperties; @Autowired
private ValidateCodeGenerator imageCodeGenerator;//图片验证码 @Autowired
private ValidateCodeGenerator smsCodeGenerator;//短信验证码 //获取session
private SessionStrategy sessionStrategy = new HttpSessionSessionStrategy(); @Autowired
private SmsCodeSender smsCodeSender; //短信验证码发送接口 /**
* 短信验证码
* @Description: TODO
* @param @param request
* @param @param response
* @param @throws IOException
* @return void
* @throws ServletRequestBindingException
* @throws
* @author lihaoyang
* @date 2018年3月7日
*/
@GetMapping("/verifycode/sms")
public void createSmsCode(HttpServletRequest request,HttpServletResponse response) throws Exception{ //调验证码生成接口方式
ValidateCode smsCode = smsCodeGenerator.generator(new ServletWebRequest(request));
sessionStrategy.setAttribute(new ServletWebRequest(request), SESSION_KEY, smsCode);
//获取手机号
String mobile = ServletRequestUtils.getRequiredStringParameter(request, "mobile");
//发送短信验证码
smsCodeSender.send(mobile, smsCode.getCode());
} }

短信验证码生成实现类,实现验证码接口,验证码的长度和过期时间做成可配置的,灵活些:

package com.imooc.security.core.validate.code;

import org.apache.commons.lang.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.context.request.ServletWebRequest; import com.imooc.security.core.properties.SecurityProperties; /**
* 短信验证码生成类
* ClassName: ImageCodeGenerator
* @Description: TODO
* @author lihaoyang
* @date 2018年3月2日
*/
@Component("smsCodeGenerator")
public class SmsCodeGenerator implements ValidateCodeGenerator { @Autowired
private SecurityProperties securityProperties; @Override
public ValidateCode generator(ServletWebRequest request) {
//生成验证码,长度从配置读取
String code = RandomStringUtils.randomNumeric(securityProperties.getCode().getSms().getLength());
return new ValidateCode(code, securityProperties.getCode().getSms().getExpireIn());
} public SecurityProperties getSecurityProperties() {
return securityProperties;
} public void setSecurityProperties(SecurityProperties securityProperties) {
this.securityProperties = securityProperties;
} }

验证码类:只有code和过期时间即可

package com.imooc.security.core.validate.code;

import java.awt.image.BufferedImage;
import java.time.LocalDateTime;
import java.time.LocalTime; /**
* 短信验证码
* ClassName: ImageCode
* @Description: 验证码
* @author lihaoyang
* @date 2018年3月1日
*/
public class ValidateCode { private String code; private LocalDateTime expireTime;//过期时间点 /**
*
* <p>Description: </p>
* @param image
* @param code
* @param expireTn 多少秒过期
*/
public ValidateCode(String code, int expireTn) {
this.code = code;
//过期时间=当前时间+过期秒数
this.expireTime = LocalDateTime.now().plusSeconds(expireTn);
} public ValidateCode(String code, LocalDateTime expireTime) {
this.code = code;
this.expireTime = expireTime;
} /**
* 验证码是否过期
* @Description: 验证码是否过期
* @param @return true 过期,false 没过期
* @return boolean true 过期,false 没过期
* @throws
* @author lihaoyang
* @date 2018年3月2日
*/
public boolean isExpired(){
return LocalDateTime.now().isAfter(expireTime);
} public String getCode() {
return code;
} public void setCode(String code) {
this.code = code;
} public LocalDateTime getExpireTime() {
return expireTime;
} public void setExpireTime(LocalDateTime expireTime) {
this.expireTime = expireTime;
} }

验证码发送抽象成接口:

package com.imooc.security.core.validate.code.sms;

/**
* 短信验证码发送接口
* ClassName: SmsCodeSender
* @Description: TODO
* @author lihaoyang
* @date 2018年3月7日
*/
public interface SmsCodeSender { /**
* 发送验证码短信
* @Description: 短信发送
* @param @param mobile 接收验证码的手机号
* @param @param code 验证码
* @return void
* @throws
* @author lihaoyang
* @date 2018年3月7日
*/
void send(String mobile,String code);
}

提供一个默认实现:做成引用该模块可覆盖默认实现的,更灵活

package com.imooc.security.core.validate.code.sms;

/**
* 默认的短信验证码发送类
* ClassName: DefaultSmsCodeSender
* @Description: TODO
* @author lihaoyang
* @date 2018年3月7日
*/
public class DefaultSmsCodeSender implements SmsCodeSender{ @Override
public void send(String mobile, String code) {
System.err.println("向手机 :"+mobile+" 发送短信验证码 :"+code);
} }

配置验证码生成器为spring的bean,,如果spring容器有该SmsCodeSender 接口的实现就用,没有了再配置,即可覆盖

package com.imooc.security.core.validate.code;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import com.imooc.security.core.properties.SecurityProperties;
import com.imooc.security.core.validate.code.sms.DefaultSmsCodeSender;
import com.imooc.security.core.validate.code.sms.SmsCodeSender; /**
* 配置验证码生成接口ValidateCodeGenerator的实际实现类的Bean
* ClassName: ValidateCodeBeanConfig
* @Description:
* 配置验证码生成接口ValidateCodeGenerator的实际实现类的Bean
* 如图片验证码的实现、短信验证码的实现
* @author lihaoyang
* @date 2018年3月5日
*/
@Configuration
public class ValidateCodeBeanConfig { @Autowired
private SecurityProperties securityProperties; /**
* @Description:
* 配置图片验证码生成bean
* @ConditionalOnMissingBean注解意思是当spring容器不存在imageCodeGenerator时才给配置一个该bean
* 作用是使程序更具可扩展性,该配置类是配置在core模块,这就意味着,如果引用该模块的项目
* 如果有一个自己的实现,实现了ValidateCodeGenerator接口,定义了自己的实现,名字也叫imageCodeGenerator时,
* 就用应用级别的实现,没有的话就用这个默认实现。
* @param @return
* @return ValidateCodeGenerator
* @throws
* @author lihaoyang
* @date 2018年3月5日
*/
@Bean
@ConditionalOnMissingBean(name="imageCodeGenerator")
public ValidateCodeGenerator imageCodeGenerator(){
ImageCodeGenerator codeGenerator = new ImageCodeGenerator();
codeGenerator.setSecurityProperties(securityProperties);
return codeGenerator;
} /**
* 配置短信验证码生成bean
* @Description:
* @param @return
* @return SmsCodeSender
* @throws
* @author lihaoyang
* @date 2018年3月7日
*/
@Bean
@ConditionalOnMissingBean(SmsCodeSender.class)
public SmsCodeSender smsCodeSender(){
return new DefaultSmsCodeSender();
}
}

验证码长度、过期时间配置类 SmsCodeProperties:

package com.imooc.security.core.properties;

/**
* 短信验证码配置类
* ClassName: ImageCodeProperties
* @Description: 图片验证码配置类
* @author lihaoyang
* @date 2018年3月2日
*/
public class SmsCodeProperties { //验证码字符个数
private int length = 4;
//过期时间
private int expireIn = 60; private String url; //拦截的url public int getLength() {
return length;
} public void setLength(int length) {
this.length = length;
} public int getExpireIn() {
return expireIn;
} public void setExpireIn(int expireIn) {
this.expireIn = expireIn;
} public String getUrl() {
return url;
} public void setUrl(String url) {
this.url = url;
} }

登录表单:

短信 登录 <br>
<form action="/authentication/mobile" method="post">
<table>
<tr>
<td>手机号:</td>
<td><input type="text" name="mobile" value="13812349876"/></td>
<td></td>
</tr>
<tr>
<td>短信验证码:</td>
<td>
<input width="100" type="text" name="smsCode"/>
<a href="/verifycode/sms?mobile=13812349876">发送验证码</a>
</td>
<td></td>
</tr>
<tr>
<td>记住我</td>
<td><input type="checkbox" name="remember-me" value="true"/></td>
</tr>
<tr>
<td colspan="2" align="right"><button type="submit">登录</button></td>
</tr>
</table>
</form>

control打印:

Spring Security构建Rest服务-0801-短信验证码发送的更多相关文章

  1. php实现的IMEI限制的短信验证码发送类

    php实现的IMEI限制的短信验证码发送类 <?php class Api_Sms{ const EXPIRE_SEC = 1800; // 过期时间间隔 const RESEND_SEC = ...

  2. PHP实现对短信验证码发送次数的限制(防机刷验证码)

    PHP实现对短信验证码发送限制(防止机刷验证码) 对用户获取短信验证码的手机号.ip.和浏览器(使用唯一标识)进行限制.本文介绍的方法是对用户每天只能通过同一浏览器或同一ip地址获取验证码10次或者同 ...

  3. Spring Security构建Rest服务-1203-Spring Security OAuth开发APP认证框架之短信验证码登录

    浏览器模式下验证码存储策略 浏览器模式下,生成的短信验证码或者图形验证码是存在session里的,用户接收到验证码后携带过来做校验. APP模式下验证码存储策略 在app场景下里是没有cookie信息 ...

  4. Spring Security构建Rest服务-0702-短信验证码登录

    先来看下 Spring Security密码登录大概流程,模拟这个流程,开发短信登录流程 1,密码登录请求发送给过滤器 UsernamePasswordAuthenticationFilter 2,过 ...

  5. Spring Security构建Rest服务-1202-Spring Security OAuth开发APP认证框架之重构3种登录方式

    SpringSecurityOAuth核心源码解析 蓝色表示接口,绿色表示类 1,TokenEndpoint 整个入口点,相当于一个controller,不同的授权模式获取token的地址都是 /oa ...

  6. Spring Security构建Rest服务-1201-Spring Security OAuth开发APP认证框架之实现服务提供商

    实现服务提供商,就是要实现认证服务器.资源服务器. 现在做的都是app的东西,所以在app项目写代码  认证服务器: 新建 ImoocAuthenticationServerConfig 类,@Ena ...

  7. Spring Security构建Rest服务-1200-SpringSecurity OAuth开发APP认证框架

    基于服务器Session的认证方式: 前边说的用户名密码登录.短信登录.第三方登录,都是普通的登录,是基于服务器Session保存用户信息的登录方式.登录信息都是存在服务器的session(服务器的一 ...

  8. Spring Security构建Rest服务-0800-Spring Security图片验证码

    验证码逻辑 以前在项目中也做过验证码,生成验证码的代码网上有很多,也有一些第三方的jar包也可以生成漂亮的验证码.验证码逻辑很简单,就是在登录页放一个image标签,src指向一个controller ...

  9. Spring Security构建Rest服务-1100-单机Session管理

    Session失效时间: springboot配置session失效时间,只需要在application.properties里配置 #session超时时间,低于60秒按60秒server.sess ...

随机推荐

  1. struts2从浅至深(五)上传与下载

    1.编写上传页面 2.编写动作方法 import java.io.File;import java.io.IOException; import javax.servlet.ServletContex ...

  2. 基于Verilog HDL的二进制转BCD码实现

    在项目设计中,经常需要显示一些数值,比如温湿度,时间等等.在数字电路中数据都是用二进制的形式存储,要想显示就需要进行转换,对于一个两位的数值,对10取除可以得到其十位的数值,对10取余可以得到个位的数 ...

  3. DFS剪枝处理HDU1010

    http://acm.hdu.edu.cn/showproblem.php?pid=1010 题意很好理解,不是最短路,而是dfs,虽然地图不算大,稍微注意一点的dfs也能险过,但是700+ms和78 ...

  4. D3_book 11.1 pie

    <!-- pie example --> <!DOCTYPE html> <meta charset="utf-8"> <style> ...

  5. UniGui之锱铢积累(仔细看这个文件)

    http://www.doc88.com/p-4022977294324.html 这个是Word文档

  6. webform获取微信用户的授权

    这是一个利用webform做出来的简单demo,微信授权,获取微信用户的基本信息.方便以后加深记忆. public partial class Index : System.Web.UI.Page { ...

  7. C#DataGridView的简单使用

    首先创建一个DataGridView控件,然后创建列(包括列名的定义), 由于我不是和数据库进行连接,只是为了输出好看一点. 删除所有数据: while (this.dataGridView1.Row ...

  8. vs2017 修改项目名称

    由于经常接到各种项目需求, 又不想重新搭建框架. 于是便想到直接修改项目名. 话不多说, 上图~ 1 重命名 解决方案 和  项目名称 2 重命名项目的应用程序名和命名空间 3 Ctrl+F 将旧的工 ...

  9. rabbitMQ的简单实例——amqp协议带数据回写机制

    rabbitMQ是一种高性能的消息队列,支持或者说它实现了AMQP协议(advanced message queue protocol高级消息队列协议). 下面简单讲一讲一个小例子.我们首先要部署好r ...

  10. Flask 语音分析

    1. 安装api      百度组件 pip install baidu-aip 2.登录百度ai账号 ,建立一个账号 http://ai.baidu.com/ from aip import Aip ...