短信验证码实现过程:
1、通过程序随机生成数字,通常是4-6位数字,或者使用字母随机产生。
生成6位验证码demo:
public String getRandNum(int charCount){
String charvalue=“”;
For(int i=0;i<charCount;i++){
char c=(char)(randomInt(0,10)+'0');
charValue+=String.valueOf(c);
}
return charValue;
}
public int randomInt(int from, int to){
Random r=new Random();
return from+r.nextInt(to-from);
}
2、当验证码生成后使用接口,通过短信平台发送手机号和验证码数据,之后短信平台再把验证码发送到手机号上;
网易易盾短信平台demo
public class SmsSendDemo {
/**
* 业务ID,易盾根据产品业务特点分配
*/
private final static String BUSINESSID = "your_business_id";
/**
* 产品密钥ID,产品标识
*/
private final static String SECRETID = "your_secret_id";
/**
* 产品私有密钥,服务端生成签名信息使用,请严格保管,避免泄露
*/
private final static String SECRETKEY = "your_secret_key";
/**
* 接口地址
*/
private final static String API_URL = "https://sms.dun.163yun.com/v2/sendsms";
/**
* 实例化HttpClient,发送http请求使用,可根据需要自行调参
*/
private static HttpClient httpClient = HttpClient4Utils.createHttpClient(100, 20, 10000, 2000, 2000);
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
// 此处用申请通过的模板id
String templateId = "xxx";
// 模板参数对应的json格式数据,例如模板为您的验证码为${p1},请于${p2}时间登陆到我们的服务器
JSONObject jsonObject = new JSONObject();
jsonObject.put("p1", "123");
jsonObject.put("p2", "20180816");
String params = jsonObject.toJSONString();
String mobile = "xx";
Map<String, String> datas = buildParam(mobile, templateId, params);
String result = HttpClient4Utils.sendPost(httpClient, API_URL, datas, Consts.UTF_8);
System.out.println("result = [" + result + "]");
}
private static Map<String, String> buildParam(String mobile, String templateId, String params) throws IOException {
Map map = new HashMap<String, String>();
map.put("businessId", BUSINESSID);
map.put("timestamp", String.valueOf(System.currentTimeMillis()));
map.put("version", "v2");
map.put("needUp", "false");
map.put("templateId", templateId);
map.put("mobile", mobile);
// 国际短信对应的国际编码(非国际短信接入请注释掉该行代码)
// map.put("internationalCode", "对应的国家编码");
map.put("paramType", "json");
map.put("params", params);
map.put("nonce", UUID.randomUUID().toString().replace("-", ""));
map.put("secretId", SECRETID);
String sign = SignatureUtils.genSignature(SECRETKEY, map);
map.put("signature", sign);
return map;
}
}
public class HttpClient4Utils {
/**
* 实例化HttpClient
*
* @param maxTotal
* @param maxPerRoute
* @param socketTimeout
* @param connectTimeout
* @param connectionRequestTimeout
* @return
*/
public static HttpClient createHttpClient(int maxTotal, int maxPerRoute, int socketTimeout, int connectTimeout,
int connectionRequestTimeout) {
RequestConfig defaultRequestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout)
.setConnectTimeout(connectTimeout).setConnectionRequestTimeout(connectionRequestTimeout).build();
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
cm.setMaxTotal(maxTotal);
cm.setDefaultMaxPerRoute(maxPerRoute);
CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(cm)
.setDefaultRequestConfig(defaultRequestConfig).build();
return httpClient;
}
/**
* 发送post请求
*
* @param httpClient
* @param url 请求地址
* @param params 请求参数
* @param encoding 编码
* @return
*/
public static String sendPost(HttpClient httpClient, String url, Map<String, String> params, Charset encoding) {
String resp = "";
HttpPost httpPost = new HttpPost(url);
if (params != null && params.size() > 0) {
List<NameValuePair> formParams = new ArrayList<NameValuePair>();
Iterator<Map.Entry<String, String>> itr = params.entrySet().iterator();
while (itr.hasNext()) {
Map.Entry<String, String> entry = itr.next();
formParams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}
UrlEncodedFormEntity postEntity = new UrlEncodedFormEntity(formParams, encoding);
httpPost.setEntity(postEntity);
}
CloseableHttpResponse response = null;
try {
response = (CloseableHttpResponse) httpClient.execute(httpPost);
resp = EntityUtils.toString(response.getEntity(), encoding);
} catch (Exception e) {
// log
e.printStackTrace();
} finally {
if (response != null) {
try {
response.close();
} catch (IOException e) {
// log
e.printStackTrace();
}
}
}
return resp;
}
}
public class SignatureUtils {
/**
* 生成签名信息
*
* @param secretKey 产品私钥
* @param params 接口请求参数名和参数值map,不包括signature参数名
* @return
* @throws UnsupportedEncodingException
*/
public static String genSignature(String secretKey, Map<String, String> params) throws UnsupportedEncodingException {
// 1. 参数名按照ASCII码表升序排序
String[] keys = params.keySet().toArray(new String[0]);
Arrays.sort(keys);
// 2. 按照排序拼接参数名与参数值
StringBuffer paramBuffer = new StringBuffer();
for (String key : keys) {
paramBuffer.append(key).append(params.get(key) == null ? "" : params.get(key));
}
// 3. 将secretKey拼接到最后
paramBuffer.append(secretKey);
// 4. MD5是128位长度的摘要算法,用16进制表示,一个十六进制的字符能表示4个位,所以签名后的字符串长度固定为32个十六进制字符。
return DigestUtils.md5Hex(paramBuffer.toString().getBytes("UTF-8"));
}
}
3、保存接口返回的信息(通常为json文本数据,转换json对象格式);
4、将手机号、短信验证码、操作时间保存下来,作为后面验证使用;
5、接收用户填写的短信验证码及其他返回数据;
6、对比提交的短信验证码与保存的验证码是否一致,同时判断提交动作是否在有效期内;
7、验证码正确且在有效期内,请求通过,处理相应的业务,否则请求不通过。