验证码
包括过期时间和redis缓存以及校验
1.设置过期时间
private Date getNextDayZeroTime() {
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DAY_OF_MONTH, 1);
calendar.set(Calendar.HOUR_OF_DAY, 2);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
return calendar.getTime();
}
2.随机生成验证码和验证码令牌
public String generateSmsCode() {
Random random = new Random();
String ch = "0123456789qwertyuiopasdfghjklzxcvbnm";
int length = ch.length();
String str = "";
for (int i = 0; i < 6; i++) {
int index = random.nextInt(length);
str += ch.substring(index, index + 1);
}
return str;
}
public String verifyCode() {
Random random = new Random();
String ch = "0123456789";
int length = ch.length();
String str = "";
for (int i = 0; i < 4; i++) {
int index = random.nextInt(length);
str += ch.substring(index, index + 1);
}
return str;
}
3.把验证码写入redis
public Tuple getCode(UserVo userVo) {
CodeVo codeVo = new CodeVo();
String validateNumber = "sms";
RedisLock redisLock = new RedisLock(redisTemplate, validateNumber, 60000, 60000);
String codeLimitKey = "key:phone:count:" + userVo.getTelPhone();
String codeLimitValue = redisLock.get(codeLimitKey);
Integer codeLimit = StringUtils.isBlank(codeLimitValue) ? 0 : Integer.parseInt(codeLimitValue);
if (codeLimit.intValue() > 5) {
return Tuple.createTuple(1, "验证码次数已达上限");
}
redisLock.set(codeLimitKey, codeLimit + 1 + "");
//redisLock.setNX(codeLimitKey, codeLimit + 1 + "");
redisLock.expireAt(codeLimitKey, this.getNextDayZeroTime());
String verifyCode = this.verifyCode();
String msgCode = this.generateSmsCode();
codeVo.setSmsCode(msgCode);
codeVo.setVerifyCode(verifyCode);
codeVo.setTelPhone(userVo.getTelPhone());
codeVo.setCodeNum(codeLimitValue);
String codeVoStr = FastJsonUtil.beanToJson(codeVo);
redisLock.setNX("key:phone:code:" + verifyCode, codeVoStr, 5 * 60);
return Tuple.createTuple(0, codeVo);
}
4.实体类
public class CodeVo {
private String verifyCode;//验证码令牌
private String codeNum;//验证码次数
private String smsCode;//短信验证码
private String telPhone;//手机号码
5.redis方法
从redis取出来
public String get(final String key) {
Object obj = null;
try {
obj = redisTemplate.execute(new RedisCallback<Object>() {
@Override
public Object doInRedis(RedisConnection connection) throws DataAccessException {
RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
byte[] data = connection.get(serializer.serialize(key));
// connection.close();
if (data == null) {
return null;
}
return serializer.deserialize(data);
}
});
} catch (Exception e) {
logger.error("get redis error, key : {}", key);
logger.error("error in RedisLock get :" + e.getMessage());
}
return obj != null ? obj.toString() : null;
}
存入redis
public void set(final String key, final String value) {
redisTemplate.execute(new RedisCallback<Serializable>() {
@Override
public Serializable doInRedis(RedisConnection connection) throws DataAccessException {
connection.set(redisTemplate.getStringSerializer().serialize(key), redisTemplate.getStringSerializer().serialize(value));
return true;
}
});
}
设置过期时间
public Boolean expireAt(String key, Date date) {
return redisTemplate.expireAt(key, date);
}
6.申请短信验证码账号
@Value("${message.url}")
private String url;
@Value("${message.appKey}")
private String appKey;
@Value("${message.appSecret}")
private String appSecret;
@Value("${message.localURL}")
private String localURL;
@Value("${message.name}")
private String name;
@Value("${message.pwd}")
private String pwd;
7.发送短信验证码
package cn.zhaocha.message;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import cn.zhaocha.common.config.MessageConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
@Service
public class XiooMsgService {
@Autowired
private MessageConfig messageConfig;
private static Logger log = LoggerFactory.getLogger(XiooMsgService.class);
public enum MsgResultCode {
SUCCUSS("0", "提交成功"), SENSITIVE("1", "含有敏感词汇"), NO_MONEY("2", "余额不足"), NO_PHONE("3", "没有号码"), BAD_SQL("4", "包含sql语句"), NO_ACCOUNT("10",
"账号不存在"), ACCOUNT_DEAD("11", "账号注销"), ACCOUNT_STOP("12", "账号停用"), BAD_IP("13", "IP鉴权失败"), BAD_FORMAT("14", "格式错误"), SYSTEM_ERROR("-1", "系统异常");
public static String codeOf(String paymentType) {
for (MsgResultCode item : values()) {
if (item.getCode().equals(paymentType)) {
return item.getMsg();
}
}
throw new RuntimeException("没有匹配的短信结果信息");
}
private String code;
private String msg;
public String getCode() {
return code;
}
public String getMsg() {
return msg;
}
MsgResultCode(String code, String msg) {
this.code = code;
this.msg = msg;
}
}
public void sendSmsCode(String phone, String smsCode) {
String content = new StringBuffer("您的验证码为" + smsCode + ",如非本人操作,请忽略本短信,本验证码有效时间5分钟。").toString();
this.sendMsg(phone, content);
}
private void sendMsg(String phone, String msg) {
if (StringUtils.isEmpty(phone) || !phone.startsWith("1")) {
return;
}
String name = messageConfig.getName();
String pwd = messageConfig.getPwd();
StringBuffer mobileString = new StringBuffer(phone);
String sign = "xx";
String stime = "";
StringBuffer extno = new StringBuffer();
try {
String resultStr = doPost(name, pwd, mobileString, msg, sign, stime, extno, messageConfig);
log.info("短信 结果" + phone + " " + resultStr);
if (resultStr.contains(",")) {
String result = resultStr.split(",")[0];
log.info(result + " " + MsgResultCode.codeOf(result));
} else {
log.info("短信 结果 没有逗号" + phone + " " + resultStr);
}
} catch (Exception e) {
log.info(e.toString());
}
}
public static String doPost(String name, String pwd, StringBuffer mobileString, String contextString, String sign, String stime, StringBuffer extno,
MessageConfig messageConfig) throws Exception {
StringBuffer param = new StringBuffer();
param.append("name=" + name);
param.append("&pwd=" + pwd);
param.append("&mobile=").append(mobileString);
param.append("&content=").append(URLEncoder.encode(contextString.toString(), "UTF-8"));
param.append("&stime=" + stime);
param.append("&sign=").append(URLEncoder.encode(sign, "UTF-8"));
param.append("&type=pt");
param.append("&extno=").append(extno);
// URL localURL = new URL("http://api.duanxin123.cn/asmx/smsservice.aspx?");
URL localURL = new URL(messageConfig.getLocalURL());
URLConnection connection = localURL.openConnection();
HttpURLConnection httpURLConnection = (HttpURLConnection) connection;
httpURLConnection.setDoOutput(true);
httpURLConnection.setRequestMethod("POST");
httpURLConnection.setRequestProperty("Accept-Charset", "utf-8");
httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
httpURLConnection.setRequestProperty("Content-Length", String.valueOf(param.length()));
OutputStream outputStream = null;
OutputStreamWriter outputStreamWriter = null;
InputStream inputStream = null;
InputStreamReader inputStreamReader = null;
BufferedReader reader = null;
String resultBuffer = "";
try {
outputStream = httpURLConnection.getOutputStream();
outputStreamWriter = new OutputStreamWriter(outputStream);
outputStreamWriter.write(param.toString());
outputStreamWriter.flush();
if (httpURLConnection.getResponseCode() >= 300) {
throw new Exception("HTTP Request is not success, Response code is " + httpURLConnection.getResponseCode());
}
inputStream = httpURLConnection.getInputStream();
resultBuffer = convertStreamToString(inputStream);
} finally {
if (outputStreamWriter != null) {
outputStreamWriter.close();
}
if (outputStream != null) {
outputStream.close();
}
if (reader != null) {
reader.close();
}
if (inputStreamReader != null) {
inputStreamReader.close();
}
if (inputStream != null) {
inputStream.close();
}
}
return resultBuffer;
}
public static String convertStreamToString(InputStream is) {
StringBuilder sb1 = new StringBuilder();
byte[] bytes = new byte[4096];
int size = 0;
try {
while ((size = is.read(bytes)) > 0) {
String str = new String(bytes, 0, size, "UTF-8");
sb1.append(str);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb1.toString();
}
}
7.在生成验证码的地方调用发送短信验证码
8.校验
String validateNumber="sms";
RedisLock redisLock=new RedisLock(redisTemplate,validateNumber,60000,10000);
String codeKey=redisLock.get("key:phone:code:"+userVo.getVerifyCode());
CodeVo codeVo= FastJsonUtil.jsonToBean(codeKey, CodeVo.class);
System.out.println(codeVo.getSmsCode());
if (!codeVo.getSmsCode().equalsIgnoreCase(userVo.getCode())) {
return Tuple.createTuple(1, "验证码错误");
}