短信验证码的实现
程序员文章站
2022-05-19 19:25:58
...
首先,需要在短信验证码公司注册个账号,我是在http://www.miaodiyun.com/这里注册的。
注册登录后,会赠送10rmb的短信费用,用来测试足够了。
登录后,用户中心-配置管理-验证码短信模版,新建一个模版,如下图
模版规则可以自己摸索,网站都有说明,填写后提交审核,审核后模版就可以使用了。
然后我们去看api接口文档
知道请求和返回有哪些参数了,就可以开始写代码了·。
在包 Utils.SMSCaptcha,新建一个类,用于生成验证码:
package Utils.SMSCaptcha;
import java.util.Random;
/**
* Created by lc on 2018/8/15.
*/
//此类用于生成6位数验证码并返回
public class RandUtil {
public static String getRandNum(){
String random=new Random().nextInt(1000000)+"";
if (random.length()<6){
return getRandNum();
}
return random;
}
}
在包 Utils.SMSCaptcha,再新建一个类,用于生成时间戳和参数sig(MD5签名)。
关于MD5,不了解可以看看这篇博文https://blog.csdn.net/wufaliang003/article/details/79782212。
代码如下:
package Utils.SMSCaptcha;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Created by lc on 2018/8/15.
*/
public class QueryUtil {
public static String queryArguments(String ACCOUNT_SID,String AUTH_TOKEN, String smsContent,String to) throws NoSuchAlgorithmException {
String timestamp = getTimestamp(); //获取时间戳
String sig = MD5(ACCOUNT_SID, AUTH_TOKEN, timestamp);//签名认证
String str = "accountSid=" + ACCOUNT_SID + "&smsContent=" +
smsContent + "&to=" + to + "×tamp=" + timestamp + "&sig=" + sig;
return str;
}
public static String MD5(String... args) throws NoSuchAlgorithmException { //动态参数
StringBuffer result = new StringBuffer();
if (args == null || args.length == 0) {
return "";
} else {
StringBuffer str = new StringBuffer();
//遍历动态参数,将其拼接到字符串变量str里
for (String string : args) {
str.append(string);
}
System.out.println("加密前:\t"+str.toString());
try {
//拿到一个MD5转换器
MessageDigest digest = MessageDigest.getInstance("MD5");
//调用加密对象的方法
byte[] bytes = digest.digest(str.toString().getBytes());
//加密动作完成后,返回的是一个字节数组,大小为16
//短信接口的请求参数需要的是一个32位的小写字符串,所以我们需要将其转换为32位的小写字符串
//遍历字节数组
for (byte b : bytes) {
String hex = Integer.toHexString(b&0xff); //转化十六进制
if (hex.length() == 1) {
result.append("0"+hex);
}else{
result.append(hex);
}
}
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
System.out.println("加密后:\t"+result.toString());
return result.toString();
}
public static String getTimestamp() {
//定义时间格式
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyyMMddHHmmss");
Date date=new Date();
//返回特定格式的时间字符串
return simpleDateFormat.format(date);
}
}
在包 Utils.SMSCaptcha,再新建一个类,用于Post请求验证码并处理返回的Json。
由于要处理Json数据,为了方便,我们要使用Json工具,导入以下Jar包。
下载链接:https://download.csdn.net/download/cc1969281777/10609156
代码如下:
package Utils.SMSCaptcha;
import net.sf.json.JSONObject;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLConnection;
import java.security.NoSuchAlgorithmException;
/**
* Created by lc on 2018/8/15.
*/
public class GetMessage {
//用户id
public static final String ACCOUNT_SID = "*******************************";//这里填写你在平台里的ACOUNT_SID
//**
public static final String AUTH_TOKEN = "*******************************";//这里填写你在平台里的ACOUNT_TOKEY
//请求地址前半部分
public static final String BASE_URL = "https://api.miaodiyun.com/20150822/industrySMS/sendSMS";//请求地址是固定的不用改
//获取验证码
public static String randNum = RandUtil.getRandNum();
//设置模版
public static String smsContent = "【云天书城】您的验证码为"+randNum+",请于"+5+"分钟内正确输入,如非本人操作,请忽略此短信。";
public static String getResult(String to) throws NoSuchAlgorithmException {
String args = QueryUtil.queryArguments(ACCOUNT_SID, AUTH_TOKEN, smsContent, to);
OutputStreamWriter out = null;
InputStream in = null;
BufferedReader br = null;
StringBuffer sb = new StringBuffer();
try {
URL url = new URL(BASE_URL);
URLConnection connection = url.openConnection(); //打开链接
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setConnectTimeout(5000); //设置链接超时
connection.setReadTimeout(10000); //设置读取超时
//提交数据
out = new OutputStreamWriter(connection.getOutputStream(),"utf-8");
out.write(args);
out.flush();
//读取返回数据
br = new BufferedReader(new InputStreamReader(connection.getInputStream(),"utf-8"));
String line = "";
while((line = br.readLine())!=null){
sb.append(line);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if (br!=null) {
br.close();
}
if (out!=null) {
out.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
JSONObject jsonObject = JSONObject.fromObject(sb.toString());
System.out.println(jsonObject);
Object object = jsonObject.get("respCode");
if (!object.equals("00000")) {
return sb.toString();
}else{
return randNum;
}
}
// 测试功能
/* public static void main(String[] args) throws NoSuchAlgorithmException {
getResult("你的手机号");
}*/
}
目前为止,就实现了请求验证码和获取请求结果(Json)了,下面在web应用投入使用。
在包Control新建一个Servlet,用于处理前端页面的获取验证码请求:
package control;
import Utils.SMSCaptcha.GetMessage;
import net.sf.json.JSONObject;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
/**
* Created by lc on 2018/8/15.
*/
@WebServlet(name = "GetMessageServlet",urlPatterns = "/GetMe")
public class GetMessageServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
String tel=request.getParameter("tel");
System.out.println("手机号"+tel+"获取手机验证码");
try {
String result = GetMessage.getResult(tel);
//验证码发送成功
if (result.length()==6){
HttpSession session = request.getSession();
//将验证码添加到session
session.setAttribute("pin",result);
//返回请求结果给浏览器
response.getWriter().write("true");
}
//验证码发送失败
else {
JSONObject jsonObject=JSONObject.fromObject(result);
Object respDesc = jsonObject.get("respDesc");
//返回错误信息给浏览器
response.getWriter().write(respDesc.toString());
}
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
}
前端注册页面:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>注册</title>
<link rel="stylesheet" href="css/Register.css">
</head>
<script src="js/jquery-3.3.1.min.js"></script>
<script>
$(document).ready(function(){
$("#register").attr("disabled", true);
$("#u").focus(
function(){
$("#span-u").css("color","#7d7d7d");
$("#span-u").text("用户名由3到15个字符组成");
}
)
$("#u").blur(
function(){
if($("#u").val().length<3){
$("#span-u").css("color","#FF5500");
$("#span-u").text("用户名不得小于3个字符!");
}
else if($("#u").val().length>15){
$("#span-u").css("color","#FF5500");
$("#span-u").text("用户名不得大于15个字符!");
}
else{
$("#span-u").css("color","crimson");
$("#span-u").text("√");
}
}
)
$("#tel").focus(
function(){
$("#span-tel").css("color","#7d7d7d");
$("#span-tel").text("请输入11位的*手机号");
}
)
$("#p1").focus(
function(){
$("#span-p1").css("color","#7d7d7d");
$("#span-p1").text("请填写密码,长度为6-16个字符");
}
)
$("#p1").blur(
function(){
if($("#p1").val().length<6){
$("#span-p1").css("color","#FF5500");
$("#span-p1").text("密码不得小于6个字符!");
}
else if($("#p1").val().length>16){
$("#span-p1").css("color","#FF5500");
$("#span-p1").text("密码不得大于16个字符!");
}
else{
$("#span-p1").css("color","crimson");
$("#span-p1").text("√");
}
}
)
$("#p2").focus(
function(){
$("#span-p2").css("color","#7d7d7d");
$("#span-p2").text("请再次输入密码");
}
)
$("#p2").blur(
function(){
if($("#p1").val()!=$("#p2").val()) {
$("#span-p2").css("color", "#FF5500");
$("#span-p2").text("两次输入的密码不一致!");
}
else if($("#p2").val().length<6){
$("#span-p2").css("color","#FF5500");
$("#span-p2").text("密码不得小于6个字符!");
}
else{
$("#span-p2").css("color","crimson");
$("#span-p2").text("√");
}
}
)
$("#checkbox").click(function () {
if ($(this).is(":checked")) {
$("#register").attr("disabled", false);
$("#register").css("background-color","#FF5500");
} else {
$("#register").attr("disabled", true);
$("#register").css("background-color","#999999");
}}
)
$("#getme").click(function(){
var tel=$("#tel").val();
$.ajax(
{
url:"/GetMe",
data:{
tel:tel
},
success:function(str){
if(str=="true"){
$("#getme").attr("value","验证码已发送")
$("#getme").attr("disabled", true);
$("#span-tel").css("color","#9f9f9f");
var time=60;
function resetTime(){
$("#span-tel").text(time+"s后可以重新获取验证码");
time--;
if(time>0) {
setTimeout(resetTime, 1000)
}
else {
$("#span-tel").text("");
$("#getme").attr("disabled", false);
$("#getme").attr("value","获取验证码")
}
}
resetTime();
}else{
$("#span-tel").css("color","#FF5500");
$("#span-tel").text(str);
}
}
}
)
})
$("#register").click(
function(){
var username=$("#u").val();
var password=$("#p1").val();
var password2=$("#p2").val();
var tel=$("#tel").val();
var pin=$("#pin").val();
if(password==password2){
$.ajax(
{
url:"/Register",
data:{
username:username,
password:password,
tel:tel,
pin:pin
},
success:function(str){
if(str=="success"){
alert("注册成功!按确定键转到登录界面");
location.href="/Login.html";
}
else if(str=="false"){
alert("注册失败!")
}
else if(str=="false1"){
alert("验证码错误!")
}
}
}
)
}
}
)
})
</script>
<body>
<div class="box">
<span class="title">注册</span>
<p class="text">
<span class="span-label">用户名:</span><input type="text" name="username" style="width: 230px" id="u">
<span class="span-darkgray" id="span-u"></span>
</p>
<p class="text">
<span class="span-label">密码:</span><input type="password" name="password" style="width: 230px" id="p1">
<span id="span-p1" class="span-darkgray"></span>
</p>
<p class="text">
<span class="span-label">确认密码:</span><input type="password" name="password" style="width: 230px" id="p2">
<span id="span-p2" class="span-darkgray"></span>
</p>
<p class="text">
<span class="span-label">手机号:</span><input type="text" style="width: 230px" id="tel"><input type="button" value="获取验证码" id="getme"/>
<span id="span-tel" class="span-darkgray"></span>
</p>
<p class="text">
<span class="span-label">验证码:</span><input type="text" name="pin" style="width: 100px" id="pin"/>
</p>
<p class="text"><span id="span-pa" class="span-red"></span></p>
<p class="text">
<input type="checkbox" name="checkbox" id="checkbox">
<label>我已阅读并同意遵守《云天书城用户服务协议》</label>
<input type="button" value="注册" class="button" id="register">
</div>
</body>
</html>
注册事件的Servlet:
package control;
import dao.Userdao;
import javabeen.User;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/**
* Created by lc on 2018/6/22.
*/
@WebServlet(name = "Register",urlPatterns = "/Register")
public class Register extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
response.setContentType("text/html;charset=utf-8");
String username = request.getParameter("username");
String password = request.getParameter("password");
String pin = request.getParameter("pin");
String tel = request.getParameter("tel");
//从Session取出短信验证码
HttpSession session = request.getSession();
String pin1 = (String) session.getAttribute("pin");
//比较验证码是否正确
if (pin.equals(pin1)) {
System.out.println(username + " " + password + " " + tel);
User user = new User(username, password, tel);
Userdao userdao = new Userdao();
boolean register = userdao.register(user);
if (register == true) {
response.getWriter().write("success");
} else {
response.getWriter().write("false");
}
}else {
response.getWriter().write("false1");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}