1、生成验证码类
package com.util;
import java.util.Timer;
import java.util.TimerTask;
/**
* @description 手机发送验证码工具类
*/
public class MessageCode extends TimerTask{
private Timer timer;
/**
* @description 短信验证码的内容
*/
private String messageCode;
/**
* @description 毫秒,默认60秒后过期
*/
private long maXtime = 180000;
/**
* @description 短信验证码长度
*/
private int length = 6;
/**
* @description 短信验证码可取值
*/
private final String charOfMessage = "0123456789";
//0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
@Override
public void run() {
this.messageCode = null;//过期后短信验证码信息置为null
this.timer.cancel();
}
/**
* @decription 使用默认值
*/
public MessageCode() {
super();
this.timer = new Timer();
genMessageCode(this.length);
this.timer.schedule(this, this.maXtime);
}
/**
* @description 自定义最大过期时间,验证码最大长度
* @param maXtime
* @param length
*/
public MessageCode(long maXtime, int length) {
super();
this.maXtime = maXtime;
this.length = length;
genMessageCode(this.length);
this.timer.schedule(this, this.maXtime);
}
/**
* @description 生成随机验证码
* @param length
* @return void 返回值类型
*/
private final void genMessageCode(int length){
StringBuffer tempB = new StringBuffer(length);
final int charOfMassegeLength = this.charOfMessage.length();
for(int i = 0; i < length; i++){
double d = Math.random();
int index = (int)(Math.floor(d * charOfMassegeLength) / 1);
tempB.append(this.charOfMessage.charAt(index));
}
this.messageCode = tempB.toString();
}
/**
* @description 获取验证码信息,如果为空表示验证码超时
* @return
* @return String 返回值类型
*/
public String getMessageCode() {
return messageCode;
}
}
2、 MessageThread.java 线程类
package com.util;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import org.apache.commons.lang.StringUtils;
/**
* @description 使用线程发送消息,以免主线程等待
*/
public final class MessageThread implements Runnable{
/**
* @description 发送请求的URL
*/
private final static String url = "http:192.168.1.127/sms/send/smsSend.action?businessName=c1&isLong=3&appName=useraccount&smsKey=powsword";
private String msg;
private String phonenumber;
@Override
public void run() {
sendMessage();
}
/**
* @description
* @return void 返回值类型
*/
private void sendMessage(){
String phone = this.phonenumber;
if(StringUtils.isBlank(this.phonenumber)){//手机号为空时,禁止消息发送
return;
}
String tempUrl = url;
try {
//经过两次转码。短消息显示正常
msg = java.net.URLEncoder.encode(msg, "UTF-8");
tempUrl = (tempUrl + "&uuid=" + java.util.UUID.randomUUID().toString().replaceAll("-", ""));
tempUrl = (tempUrl + "&phone=" + phone);
tempUrl = (tempUrl + "&content=" + java.net.URLEncoder.encode(msg, "UTF-8"));
URLConnection connection = new URL(tempUrl).openConnection();
connection.setConnectTimeout(2000);
connection.setReadTimeout(2000);
connection.connect();
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
// String x = reader.readLine();
// System.out.println(x);
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* @decription 初始化发送信息线程数据
* @param msg
* @param phonenumber
*/
public MessageThread(String msg, String phonenumber) {
super();
this.msg = msg;
this.phonenumber = phonenumber;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public String getPhonenumber() {
return phonenumber;
}
public void setPhonenumber(String phonenumber) {
this.phonenumber = phonenumber;
}
}
3、发送消息工具类
package com.util;
/**
* @description <p>发送消息工具类,具体的消息发送方法参见MessageThread.java</p>
* <p>调用sendMessage方法 ,传入消息内容和手机号发送消息。</p>
* <p>当手机号为空时,不发送消息</p>
*/
public final class MessageUtil {
/**
* @description 调用此方法发送消息内容
* @param msg 发送消息内容
* @param phone 发送消息的手机号。当手机号为空时,不发送消息
*/
public final static void sendMessage (String msg, String phone){
new Thread(new MessageThread(msg, phone)).start();
}
}
——————————————————————————————————————————————————————
——————————————————————————————————————————————————————
短信重置密码类调用以上工具示例:
package com.ww.k.a.action;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.ww.k.a.action.form.WwAc01UserForm;
import com.ww.k.a.action.form.WwkaForm;
import com.ww.k.a.manager.WwkaMng;
import com.ww.k.a.manager.dto.WwkaDto;
import com.ww.z.util.MessageCode;
import com.ww.z.util.MessageUtil;
import com.util.DtoUtil;
import com.JSONUtil;
import com.validate.CJobBeanValidator;
@Controller
@RequestMapping(value = "/k/a/")
public class WwkaAct {
@Autowired
private WwkaMng wwkaMng;
/**
*
* @Description: 找回密码页面入口
* @param request
* @param response
* @param model
*/
@RequestMapping(value = "wwka_cont.html")
public String cont(HttpServletRequest request, HttpServletResponse response, ModelMap model) {
return "k/a/wwka_contnew";
}
/**
*
* @Description: 找回密码 通过邮箱
* @param form
* @param find
* @param req
* @param resp
*/
@ResponseBody
@RequestMapping(value = "wwka_mail.html")
public String doFindBackMail(WwkaForm form,HttpServletRequest req, HttpServletResponse resp)throws IOException {
Map<String, String> result = new HashMap<String, String>();
if ("".equals(form.getAccount())
|| "".equals(form.getMail())
|| !(wwkaMng.hasuser(form.getAccount(), form.getMail()))) {
result.put("hasError", "2");//帐号或者邮箱不正确
} else {
result.put("hasError", "1");//帐号、邮箱正确
WwkaDto maildto = new WwkaDto();
DtoUtil.copyProperties(form, maildto);
wwkaMng.sentmail(req,maildto);//邮件找回密码
}
JSONObject json = JSONObject.fromObject(result);
return json.toString();
}
/**
*
* @Description: 通过账号名获取Dto,从而获取安全问题
* @param account
* @param req
* @param resp
* @return
* @throws IOException
*/
@ResponseBody
@RequestMapping(value = "wwka_findQ.html")
public String doFindQ(String account,HttpServletRequest req, HttpServletResponse resp)throws IOException {
Map<String, String> result = new HashMap<String, String>();
WwkaDto dtoQ = wwkaMng.findoutQ(account);
String question = dtoQ.getQuestion();
if("".equals(question)||question==null){
result.put("noQ", "1");
}else{
result.put("question", question);
}
JSONObject json = JSONObject.fromObject(result);
return json.toString();
}
/**
*
* @Description: 找回密码 之 安全问题找回密码
* @param form
* @param req
* @param resp
* @return
* @throws IOException
*/
@ResponseBody
@RequestMapping(value = "wwka_question.html")
public String doFindByQ(WwkaForm form,HttpServletRequest req, HttpServletResponse resp)throws IOException {
Map<String, String> result = new HashMap<String, String>();
if ("".equals(form.getAccount2())
|| form.getAccount2()==null
|| !(wwkaMng.hasQ(form.getAccount2(), form.getAnswer()))) {
result.put("hasError", "2");//帐号或者答案不正确
JSONObject json = JSONObject.fromObject(result);
return json.toString();
} else {
//生成6位随机数作为找回的新密码
Random rd = new Random();
int num = rd.nextInt(1000000);
while(num < 100000){
num = rd.nextInt(1000000);
}
String passwd = String.valueOf(num);
//获得原来数据
WwkaDto dtopwd = wwkaMng.findoutQ(form.getAccount2());
dtopwd.setPassword(passwd);
//将新密码同步到数据库
wwkaMng.resetNewPwd(dtopwd);
//返回给用户的新密码
result.put("showMail", dtopwd.getMail());
result.put("showQ", dtopwd.getQuestion());
result.put("showLnum", dtopwd.getLoginNum()!=null?String.valueOf(dtopwd.getLoginNum()):"0");
result.put("showLtime", dtopwd.getLoginTime()!=null?String.valueOf(dtopwd.getLoginTime()):"无");
result.put("showRtime", String.valueOf(dtopwd.getRegisterTime()));
result.put("newPwd", passwd);
result.put("showaccount", form.getAccount2());
result.put("hasError", "1");//帐号、答案正确
}
JSONObject json = JSONObject.fromObject(result);
return json.toString();
}
/**
* @description 发送手机验证码,校验账号是否存在,并且账号的手机号码与输入的手机号码是否一致
* @param request
* @param response
* @param phonenumber
* @param account
* @return void 返回值类型
*/
@ResponseBody
@RequestMapping("wwka_getcode.html")
public void getCode(HttpServletRequest request, HttpServletResponse response, String phonenumber, String account){
StringBuffer errerB = new StringBuffer();
if(StringUtils.isBlank(account)){
errerB.append("请输入您的个人账号。<br>");
}else if(!account.matches("^[1-9]{1}[0-9]{16}[0-9Xx]{1}$")){
errerB.append("您的个人账号输入错误。<br>");
}
if(StringUtils.isBlank(phonenumber)){
errerB.append("请输入手机号码。<br>");
}else if(!phonenumber.matches("^1[0-9]{10}$")){
errerB.append("您的手机号码输入错误。<br>");
}
if(errerB.toString().endsWith("<br>")){//如果以<br>结尾,去掉<br>
errerB.setLength(errerB.length() - 4);
}
Map<String, String> rs = new HashMap<String, String>();
//校验不通过
if(errerB.length() != 0){
rs.put("msg", errerB.toString());
rs.put("status", "-1");
JSONUtil.write(response, rs);
return;
}
//校验通过,判断账号是否存在
WwAc01UserForm form = wwkaMng.getUserInfo(account);
if(form == null){
rs.put("msg", "您输入的账号不存在。");
rs.put("status", "-1");
JSONUtil.write(response, rs);
return;
}else if(!phonenumber.equals(form.getPhonenumber())){//账号存在,判断手机号码是否与系统一致
rs.put("msg", "您输入的手机账号与该账号在系统中预留的手机号码不一致。");
rs.put("status", "-1");
JSONUtil.write(response, rs);
return;
}
//以上都通过,发送验证码
HttpSession session = request.getSession();
MessageCode code = new MessageCode();
String msg = code.getMessageCode();
session.setAttribute(session.getId() + "_resetpassword", code);
MessageUtil.sendMessage(msg, phonenumber);
rs.put("msg", "手机验证码已由系统发出,请您注意查收。");
rs.put("status", "1");
JSONUtil.write(response, rs);
}
/**
* @description 重置密码。密码发送到系统中预留的手机号码
* @param request
* @param response
* @param phonenumber
* @param account
* @param phonecode
* @return void 返回值类型
*/
@ResponseBody
@RequestMapping("wwka_resetpsw.html")
public void resetPassword(HttpServletRequest request, HttpServletResponse response, String phonenumber, String account, String phonecode){
//先取出验证码,以免校验时过期
HttpSession session = request.getSession();
Map<String, String> rs = new HashMap<String, String>();
Object obj = session.getAttribute(session.getId() + "_resetpassword");
if(obj == null){
rs.put("msg", "请先获取手机验证码。");
rs.put("status", "-1");
JSONUtil.write(response, rs);
return;
}else{
MessageCode code = (MessageCode)obj;
String codestr = code.getMessageCode();
if(StringUtils.isBlank(codestr)){
rs.put("msg", "您输入手机验证码已过期,请重新获取。");
rs.put("status", "-1");
JSONUtil.write(response, rs);
return;
}else{//再次校验信息是否合法
StringBuffer errerB = new StringBuffer();
if(StringUtils.isBlank(account)){
errerB.append("请输入您的个人账号。<br>");
}else if(!account.matches("^[1-9]{1}[0-9]{16}[0-9Xx]{1}$")){
errerB.append("您的个人账号输入错误。<br>");
}
if(StringUtils.isBlank(phonenumber)){
errerB.append("请输入手机号码。<br>");
}else if(!phonenumber.matches("^1[0-9]{10}$")){
errerB.append("您的手机号码输入错误。<br>");
}
if(StringUtils.isBlank(phonecode)){
errerB.append("请输入手机接收到验证码。<br>");
}else if(!phonecode.matches("^[0-9]{6}$")){
errerB.append("您的手机验证码输入格式不正确。<br>");
}
if(errerB.toString().endsWith("<br>")){//如果以<br>结尾,去掉<br>
errerB.setLength(errerB.length() - 4);
}
//校验不通过
if(errerB.length() != 0){
rs.put("msg", errerB.toString());
rs.put("status", "-1");
JSONUtil.write(response, rs);
return;
}
//校验通过,判断账号是否存在
WwAc01UserForm form = wwkaMng.getUserInfo(account);
if(form == null){
rs.put("msg", "您输入的账号不存在。");
rs.put("status", "-1");
JSONUtil.write(response, rs);
return;
}else if(!phonenumber.equals(form.getPhonenumber())){//账号存在,判断手机号码是否与系统一致
rs.put("msg", "您输入的手机账号与该账号在系统中预留的手机号码不一致。");
rs.put("status", "-1");
JSONUtil.write(response, rs);
return;
}
//以上都通过
if(codestr.equals(phonecode)){//验证码正确重置密码
//生成随机验证码
String password = new MessageCode().getMessageCode();
WwkaDto dto = new WwkaDto();
dto.setAccount(account);
dto.setPassword(password);
//重置密码
wwkaMng.resetNewPwd(dto);
String msg = "您的个人账号密码已重置为:" + password
+ ",请您及时使用重置的新密码登陆并修改密码。";
MessageUtil.sendMessage(msg, phonenumber);
session.removeAttribute(session.getId() + "_resetpassword");
rs.put("msg", "您个人账号的密码已发送到您的手机。请您及时登陆并修改密码。");
rs.put("status", "1");
JSONUtil.write(response, rs);
}else{
rs.put("msg", "您输入的手机验证码不正确,请重新输入。");
rs.put("status", "-1");
JSONUtil.write(response, rs);
}
}
}
}
}
前端页面在此省略。