发送注册验证码
* 验证码需求:
* 1.后台随机产生4个字符
* 2.1分钟以内只能发送1次验证码
* 3.超过1分钟,但在5分钟以内,发送的验证码依然是第一次产生的验证码字符
* 4.超过了5分钟以后,产生全新的验证码
*
前端使用什么框架先不管
依赖配置
短信依赖包 redis配置,因为验证码和手机号存储在redis中
短信平台使用的建网 sms ,http://www.smschinese.cn/ 可以免费使用5条 测试即可
注意 配置接口的 账户名 和 密钥 每个人是不同的,复制过去记得更改
短信签名必须要设置,不能乱设 会被屏蔽短信发不出来 切记
短信依赖包
<dependency>
<groupId>commons-httpclientgroupId>
<artifactId>commons-httpclientartifactId>
<version>3.1version>
dependency>
redis jar包
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
dependency>
使用redis前,要先配置连接,在application.properties配置,记得开启redis-server
# redis 属性信息
## redis数据库索引(默认为0)
spring.redis.database=0
## redis服务器地址
spring.redis.host=localhost
## redis服务器连接端口
spring.redis.port=6379
## redis服务器连接密码(默认为空)
## spring.redis.password=123456
## 连接池最大连接数(使用负值表示没有限制)
spring.redis.jedis.pool.max-active=8
## 连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=8
## 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=-1ms
## 连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=0
创建一个工具类 StrUtils.getComplexRandomString ()// 获取随机字符 位数自己输入
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
* @author yaohuaipeng
* @date 2018/10/26-16:16
*/
public class StrUtils {
/**
* 把逗号分隔的字符串转换字符串数组
*
* @param str
* @return
*/
public static String[] splitStr2StrArr(String str,String split) {
if (str != null && !str.equals("")) {
return str.split(split);
}
return null;
}
/**
* 把逗号分隔字符串转换List的Long
*
* @param str
* @return
*/
public static List<Long> splitStr2LongArr(String str) {
String[] strings = splitStr2StrArr(str,",");
if (strings == null) return null;
List<Long> result = new ArrayList<>();
for (String string : strings) {
result.add(Long.parseLong(string));
}
return result;
}
/**
* 把逗号分隔字符串转换List的Long
*
* @param str
* @return
*/
public static List<Long> splitStr2LongArr(String str,String split) {
String[] strings = splitStr2StrArr(str,split);
if (strings == null) return null;
List<Long> result = new ArrayList<>();
for (String string : strings) {
result.add(Long.parseLong(string));
}
return result;
}
public static String getRandomString(int length) {
String str = "0123456789";
Random random = new Random();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < length; i++) {
int number = random.nextInt(10);
sb.append(str.charAt(number));
}
return sb.toString();
}
public static String getComplexRandomString(int length) {
String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
Random random = new Random();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < length; i++) {
int number = random.nextInt(62);
sb.append(str.charAt(number));
}
return sb.toString();
}
public static String convertPropertiesToHtml(String properties){
//1:容量:6:32GB_4:样式:12:塑料壳
StringBuilder sBuilder = new StringBuilder();
String[] propArr = properties.split("_");
for (String props : propArr) {
String[] valueArr = props.split(":");
sBuilder.append(valueArr[1]).append(":").append(valueArr[3]).append("
");
}
return sBuilder.toString();
}
}
创建短信发送类 配置接口,其它类调用这个类的send方法传入手机号和发送内容即可
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
import java.io.IOException;
public class SendMsgUtils {
private static final String UID = "amazingwest";//这是建网SMS 上的登陆账号
private static final String KEY = "d41d8cd98f00b204e980"; //这是密钥
/**
* 手机发送短信
* @param phone 手机号码
* @param context 发送短信内容
*/
public static void send(String phone, String context) {
PostMethod post = null;
try {
//创建Http客户端
HttpClient client = new HttpClient();
//创建一个post方法
post = new PostMethod("http://utf8.api.smschinese.cn");
//添加请求头信息
post.addRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf8");//在头文件中设置转码
NameValuePair[] data = {new NameValuePair("Uid", UID),
new NameValuePair("Key", KEY),
new NameValuePair("smsMob", phone),
new NameValuePair("smsText", context)};
//设置请求体
post.setRequestBody(data);
//执行post方法
client.executeMethod(post);
//获取响应头信息
Header[] headers = post.getResponseHeaders();
//获取状态码
int statusCode = post.getStatusCode();
System.out.println("statusCode:" + statusCode);
//循环打印头信息
for (Header h : headers) {
System.out.println(h.toString());
}
//获取相应体
String result = new String(post.getResponseBodyAsString().getBytes("utf8"));
System.out.println(result); //打印返回消息状态
} catch (IOException e) {
e.printStackTrace();
} finally {
if (post != null) {
//关闭资源
post.releaseConnection();
}
}
}
}
创建注册常量类,主要用来区分验证码是用来注册还是登陆或者找回密码,
/**
* 验证码常量
*/
public class VerificationConstant {
//用户注册常量
public static final String USER_REG = "user_reg";
}
前台点击发送验证码 首先要考虑多个用户同时注册,key值不能写死
首先根据手机号加注册标识(KEY)判断redis中值value是否存在,不存在就创建一个键,key为手机号+加注册标识,
判断时间,就是创建redis键值对的时候就,value会加上一个当前时间戳,取value第一次创建的时间会分割value 拿当前时间戳减去第一次创建的时间戳就能得出具体的时间
第一次创建键值 设置键的存活时间为5分钟 300秒
发送验证码短信,前端传来手机号码,在这里进行业务逻辑判断 不需要判断手机号是否注册,这是其它类的事情 使用redisTemplate 就必须得 引入redis jar包
StrUtils.getComplexRandomString(4) 这就是上面创建的工具类中的一个方法,创建4位字符的随机数,
StringUtils.isEmpty 是 import org.springframework.util.StringUtils 别弄错了
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.concurrent.TimeUnit;
@Service
public class VerificationCodeServiceImpl implements IVerificationCodeService {
@Autowired
private RedisTemplate redisTemplate;
/**
* 发送注册验证码
* 验证码需求:
* 1.后台随机产生4个字符
* 2.1分钟以内只能发送1次验证码
* 3.超过1分钟,但在5分钟以内,发送的验证码依然是第一次产生的验证码字符
* 4.超过了5分钟以后,产生全新的验证码
* @return
*/
@Override
public void sendRegisterVerificationCode(String phone) throws CustomException {
//随机产生4个字符
String value = StrUtils.getComplexRandomString(4);
//在redis中通过key获取对应的值 value:时间戳
String valueCode = (String) redisTemplate.opsForValue().get(phone + ":" + VerificationConstant.USER_REG);
//如果不为空,就意味着验证码没有过期,依然是在5分钟以内
if(!StringUtils.isEmpty(valueCode)){
//开始时间戳
String beginTimer = valueCode.split(":")[1];
if(System.currentTimeMillis()-Long.valueOf(beginTimer)<=60*1000){
//自定义异常,自己创建一个就可以了
throw new CustomException("亲!一分钟以内不能发送多次验证码!!");
}
//证明是超过了1分钟,但依然在5分钟以内,还是用之前的验证码
value = valueCode.split(":")[0];
}
//存储redis中,设置有效期是5分钟 k=phone:USER_REG v= value:时间戳
// RedisUtil.set(phone:USER_REG, value:System.currentTimeMillis(), 5MIN);
redisTemplate.opsForValue().set(phone + ":" + VerificationConstant.USER_REG,
value + ":" + System.currentTimeMillis(), 5, TimeUnit.MINUTES);
//发送手机验证码
String context = "尊敬的用户,您的验证码为:" + value + ",请您在5分钟以内完成注册!!";
//发送短信
// SendMsgUtils.send(phone, context);
System.out.println(context);
}
}
短信发送后返回值 说 明
-1 没有该用户账户
-2 接口密钥不正确 [查看密钥]
不是账户登陆密码
-21 MD5接口密钥加密不正确
-3 短信数量不足
-11 该用户被禁用
-14 短信内容出现非法字符
-4 手机号格式不正确
-41 手机号码为空
-42 短信内容为空
-51 短信签名格式不正确
接口签名格式为:【签名内容】
-52 短信签名太长
建议签名10个字符以内
-6 IP限制
大于0 短信发送数量
大功告成