1.7 操作界面
操作界面如下:
收到邮件
输入验证码268111,进入修改密码界面。
点击【提交】,可以设置新密码。
2.用JAVA实现短信验证
2.1 短信第三方平台设置
发送短信,需要使用第三方平台,这里我使用的是榛子网(http://sms_developer.zhenzikj.com/zhenzisms_user/index.html),注册登录进去,建议充20元钱,可以发送500条短信。
进入应用管理-我的应用,记住AppId和AppSecret,下面编码的时候要用。
进入短信管理-短信模板,记住模板ID,下面编码的时候要用。编辑内容。
注意:
1. 占位符格式:{数字},从{1}、{2}开始顺序填写。示例: 验证码:{1},{2}内有效,请勿泄漏给他人使用。
2. 每个账号最多创建20个模板
3. 个人账号创建的短信正文模板每个变量取值最多支持12个字。企业认证用户没有变量取值长度限制。
4. 模板中不能含有短信签名,比如【xx】
5. 模板必须体现实际业务,除变量以外的文本内容必须可判读短信含义和使用场景。
特别注意第1条,{1}、{2}我们将在程序中进行变量赋值。我的短信模板为:
“验证码为{1}:1分钟内有效,请勿泄漏给他人使用。”,里面仅有一个变量。
上代码。
2.2 Java代码
GetMessage.java
package cn.com.service; import com.zhenzi.sms.ZhenziSmsClient; import java.math.BigInteger; import java.security.MessageDigest; import java.util.HashMap; import java.util.Map; import java.util.Random; public class GetMessage { //短信平台相关参数 //这个不用改 public static String getCode(String memPhone){ String apiUrl = "https://sms_developer.zhenzikj.com"; //榛子云系统上获取 String appId = "109473"; String appSecret = "3592cfbd-0877-4cac-b720-ac4a55cefc77"; try { //随机生成验证码 String code = String.valueOf(new Random().nextInt(999999)); //将验证码通过榛子云接口发送至手机 ZhenziSmsClient client = new ZhenziSmsClient(apiUrl, appId, appSecret); Map<String, Object> params = new HashMap<String, Object>(); //前台输入的手机号 params.put("number", memPhone); params.put("message", code); //这个模板id对应的是榛子云个人中心的模板id params.put("templateId", 5948); String[] templateParams = new String[1]; templateParams[0] = code; params.put("templateParams", templateParams); String result = client.send(params); int length = result.toCharArray().length; result = result.substring(0,length-1)+",\"mycode\":\""+code+"\"}"; return result; } catch (Exception e) { e.printStackTrace(); return ""; } }
在这里:
- String appId = "109473"; //为榛子网的用户ID
- String appSecret = "3592cfbd-0877-4cac-b720-ac4a55cefc77";//为榛子网的用户密码
- …
- params.put("templateId", 5948);//榛子网的模板ID
- String[] templateParams = new String[1]; //向模板中传参数
- templateParams[0] = code;
2.3 HTML代码
phone.html
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>找回密码</title> </head> <body> <form method="post" name="myForm" action="jsp/sms.jsp"> <div>用户名:<input type="text" name="username" maxlength="50" value=""></div> <div>手机号: <input type="tel" name="number"></div> <div><button type="submit" class="sub-btn">获取验证码</button></div> </form> </body> </html>
3.4 jsp实现
sms.jsp
<%@ page contentType="text/html; charset=gb2312" %> <%@ page language="java" %> <%@ page import="net.sf.json.JSONObject" %> <%@ page import="com.mysql.jdbc.Driver" %> <%@ page import="java.sql.*" %> <%@ page import="cn.com.service.*" %> <%@ include file="db/checkfromdb.jsp"%> <!DOCTYPE html> <% String name=request.getParameter("username"); String number=request.getParameter("number"); Connection conn = connectDB(); ResultSet rs = getrs(name,"",number,"",conn); if(!(rs.getString("mycount")).equals("0")){ String message = GetMessage.getCode(number); JSONObject json = JSONObject.fromObject(message); if((json.get("code").toString()).equals("0")&&(json.get("data").toString()).equals("发送成功")){ String mycode = json.get("mycode").toString(); mycode=code.getSHA256StrJava(mycode); %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312"> <title>输入验证码</title> <script type="text/javascript" src="../js/sh256.js"></script> <script type="text/javascript" > function checkcode() { var my = document.forms["myForm"]["jym"].value; if (my.length!=6){ alert("验证码应该为6位!"); return false; } my = SHA256(my); if(my!="<%=mycode%>"){ alert("验证码错误!"); return false; }else return true; } </script> </head> <form method="post" action="setpassword.jsp" name="myForm" onsubmit="return checkcode()"> 验证码:<input type="number" name="jym" maxlength="50" value=""><br> <input type="submit" value="提交"> </form> </body> </html> <% session.setAttribute("code" , mycode); } session.setAttribute("uername" , name); }else{ out.print("注册的用户名和手机不匹配,请<a href=\"../phone.html\">,重新输入</a>"); } %>
用户输入通过短信收到的6位编码,在JS端进行SH256编码后进行比对。
注:更安全的做法可以通过Ajax方法来实现。
3.5安全编码
为了安全性,方式用户在发包以后,黑客截包修改电话号码,所以需要获得电话号码后,需要校验是否与该用户注册的电话号码用户一致,同样调用checkfromdb.jsp中的函数,完成这个功能。
3.6 操作界面
操作界面如下:
手机收到验证码。
输入验证码
点击【提交】,可以设置新密码。
3.SH256 散列js代码实现
sh256.js
/** * * Secure Hash Algorithm (SHA256) * http://www.webtoolkit.info/ * * Original code by Angel Marin, Paul Johnston. * **/ function SHA256(s){ var chrsz = 8; var hexcase = 0; function safe_add (x, y) { var lsw = (x & 0xFFFF) + (y & 0xFFFF); var msw = (x >> 16) + (y >> 16) + (lsw >> 16); return (msw << 16) | (lsw & 0xFFFF); } function S (X, n) { return ( X >>> n ) | (X << (32 - n)); } function R (X, n) { return ( X >>> n ); } function Ch(x, y, z) { return ((x & y) ^ ((~x) & z)); } function Maj(x, y, z) { return ((x & y) ^ (x & z) ^ (y & z)); } function Sigma0256(x) { return (S(x, 2) ^ S(x, 13) ^ S(x, 22)); } function Sigma1256(x) { return (S(x, 6) ^ S(x, 11) ^ S(x, 25)); } function Gamma0256(x) { return (S(x, 7) ^ S(x, 18) ^ R(x, 3)); } function Gamma1256(x) { return (S(x, 17) ^ S(x, 19) ^ R(x, 10)); } function core_sha256 (m, l) { var K = new Array(0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, 0xE49B69C1, 0xEFBE4786, 0xFC19DC6, 0x240CA1CC, 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0xC6E00BF3, 0xD5A79147, 0x6CA6351, 0x14292967, 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2); var HASH = new Array(0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19); var W = new Array(64); var a, b, c, d, e, f, g, h, i, j; var T1, T2; m[l >> 5] |= 0x80 << (24 - l % 32); m[((l + 64 >> 9) << 4) + 15] = l; for ( var i = 0; i<m.length; i+=16 ) { a = HASH[0]; b = HASH[1]; c = HASH[2]; d = HASH[3]; e = HASH[4]; f = HASH[5]; g = HASH[6]; h = HASH[7]; for ( var j = 0; j<64; j++) { if (j < 16) W[j] = m[j + i]; else W[j] = safe_add(safe_add(safe_add(Gamma1256(W[j - 2]), W[j - 7]), Gamma0256(W[j - 15])), W[j - 16]); T1 = safe_add(safe_add(safe_add(safe_add(h, Sigma1256(e)), Ch(e, f, g)), K[j]), W[j]); T2 = safe_add(Sigma0256(a), Maj(a, b, c)); h = g; g = f; f = e; e = safe_add(d, T1); d = c; c = b; b = a; a = safe_add(T1, T2); } HASH[0] = safe_add(a, HASH[0]); HASH[1] = safe_add(b, HASH[1]); HASH[2] = safe_add(c, HASH[2]); HASH[3] = safe_add(d, HASH[3]); HASH[4] = safe_add(e, HASH[4]); HASH[5] = safe_add(f, HASH[5]); HASH[6] = safe_add(g, HASH[6]); HASH[7] = safe_add(h, HASH[7]); } return HASH; } function str2binb (str) { var bin = Array(); var mask = (1 << chrsz) - 1; for(var i = 0; i < str.length * chrsz; i += chrsz) { bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (24 - i%32); } return bin; } function Utf8Encode(string) { string = string.replace(/\r\n/g,"\n"); var utftext = ""; for (var n = 0; n < string.length; n++) { var c = string.charCodeAt(n); if (c < 128) { utftext += String.fromCharCode(c); } else if((c > 127) && (c < 2048)) { utftext += String.fromCharCode((c >> 6) | 192); utftext += String.fromCharCode((c & 63) | 128); } else { utftext += String.fromCharCode((c >> 12) | 224); utftext += String.fromCharCode(((c >> 6) & 63) | 128); utftext += String.fromCharCode((c & 63) | 128); } } return utftext; } function binb2hex (binarray) { var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; var str = ""; for(var i = 0; i < binarray.length * 4; i++) { str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) + hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF); } return str; } s = Utf8Encode(s); return binb2hex(core_sha256(str2binb(s), s.length * chrsz)); }