- 1. 发送验证码
- 1.1 前端实现
- 1.2 后端实现
- 1.2.1 步骤分析
- 1.2.2 步骤实现
- 2. 注册
- 3. 加密加盐保存密码和密码校验
1. 发送验证码
1.1 前端实现
sendSmsCode(event){ //只有vue事件绑定才能调用vue的方法
let el = event.currentTarget;
if(!$("#mobileregistermodel-mobile").valid()) {
$("#mobileregistermodel-mobile").focus();
return;
}
if(!$("#password").valid()) {
$("#password").focus();
return;
}
if(!$("#captcha").valid()) {
$("#captcha").focus();
return;
}
if($(el).prop("disabled") == true || $(el).data("doing") == true) {
return;
}
if($(el).data("doing")) {
return;
}
$(el).data("doing", true);
// 获取短信验证码
var target = el; //vue对象
var mobile = $("#mobileregistermodel-mobile").val();
var captcha = $("#captcha").val();
var codeUuid = $("#codeUuid").val();
var params = {
mobile: mobile,
captcha: captcha,
codeUuid: codeUuid
};
var _this = this; //vue对象
this.$http.post('/user/register/sendSmsCode',params).then(result=>{
if(result.data.success) {
// 开始倒计时
_this.countdown(target, "获取短信验证码");
} else {
$.validator.showError($("#mobileregistermodel-sms_captcha"), result.data.message);
// 失败后点击验证码
if($("#captcha-image").size() > 0) {
$("#captcha").val("");
$("#captcha-image").click();
}
}
$(target).data("doing", false);
});
},
countdown(obj, msg) {
obj = $(obj);
var _this = this;
if(this.wait <= 0) {
obj.prop("disabled", false);
obj.html(msg);
this.wait = 60;
} else {
if(msg == undefined || msg == null) {
msg = obj.html();
}
obj.prop("disabled", true);
obj.html(this.wait + "秒后重新获取");
this.wait--;
setTimeout(function() {
_this.countdown(obj, msg)
}, 1000)
}
}
1.2 后端实现
1.2.1 步骤分析
- controller提供获取短信验证码的接口
- 提供校验图片验证码的方法
- 提供校验手机用户是否已经存在的方法
- 提供发送验证码所需的方法
1.2.2 步骤实现
- controller提供获取短信验证码的接口
package cn.wangningbo.hrm.web.controller;
import cn.wangningbo.hrm.service.IImageValidateCodeService;
import cn.wangningbo.hrm.service.ISsoService;
import cn.wangningbo.hrm.util.AjaxResult;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
@RestController
@RequestMapping("/register")
public class RegisterController {
@Autowired
private IImageValidateCodeService iImageValidateCodeService;
@Autowired
private ISsoService iSsoService;
@Autowired
private ISmsCodeService iSmsCodeService;
@PostMapping("/sendSmsCode")
public AjaxResult sendSmsCode(@RequestBody Map params) {
// 获取前台传过来的uuid,用于获取验证码
String codeUuid = (String) params.get("codeUuid");
// 获取用户输入的图片验证码
String captcha = (String) params.get("captcha");
// 获取用户输入的手机号
String mobile = (String) params.get("mobile");
//参数合法性校验 // 判断是不是空
if (StringUtils.isBlank(mobile) || StringUtils.isBlank(codeUuid) || StringUtils.isBlank(captcha)) {
return AjaxResult.me().setSuccess(false).setMessage("系统错误!请输入相关内容!");
}
// 图形验证码校验
AjaxResult ajaxResult = iImageValidateCodeService.validate(codeUuid, captcha);
if (!ajaxResult.isSuccess())
return ajaxResult;
//校验手机用户是否存在
ajaxResult = iSsoService.validateSso(mobile);
if (!ajaxResult.isSuccess())
return ajaxResult;
// 发送短信验证码
return iSmsCodeService.sendSmsCode(mobile);
}
}
- 提供校验图片验证码的方法
IService
AjaxResult validate(String codeUuid, String captcha);
ServiceImpl
@Override
public AjaxResult validate(String codeUuid, String captcha) {
// 从redis中根据前端传过来的uuid作为key查询图片验证码
String code = redisClient.get(codeUuid);
if (StringUtils.isBlank(code))
// 过期了,返回结果
return AjaxResult.me().setSuccess(false).setMessage("请输入正确图形验证码!");
if (!code.equals(captcha))
// 用户输入的验证码不正确,返回结果
return AjaxResult.me().setSuccess(false).setMessage("请输入正确图形验证码!");
// 用户输入的验证码正确
return AjaxResult.me();
}
- 提供校验手机用户是否已经存在的方法
IService
/**
* 校验该手机用户是否已经存在
* @param mobile
* @return
*/
AjaxResult validateSso(String mobile);
ServiceImpl
@Autowired
private SsoMapper ssoMapper;
@Override
public AjaxResult validateSso(String mobile) {
// 使用手机号作为条件去数据库中查询
List ssos =
ssoMapper.selectList(new EntityWrapper().eq("phone", mobile));
// 如果查询的结果不为空并且list的长度大于0,说明数据库中已经存在
if (ssos != null && ssos.size() > 0)
// 进入到if判断里面说明已经存在,返回不可注册即可
return AjaxResult.me().setSuccess(false).setMessage("用户已存在!直接登录或者找回密码继续使用!");
// 程序能走到这里,说明数据库中不存在该手机用户,返回可用继续注册
return AjaxResult.me();
}
- 提供发送验证码所需的方法
IService
/**
* 发送验证码
*
* @param mobile
* @return
*/
AjaxResult sendSmsCode(String mobile);
ServiceImpl
package cn.wangningbo.hrm.service.impl;
import cn.wangningbo.hrm.client.RedisClient;
import cn.wangningbo.hrm.service.ISmsCodeService;
import cn.wangningbo.hrm.util.AjaxResult;
import cn.wangningbo.hrm.util.SmsHelper;
import cn.wangningbo.hrm.util.StrUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Date;
@Service
public class SmsCodeServiceImpl implements ISmsCodeService {
@Autowired
private RedisClient redisClient;
@Autowired
private SmsHelper smsHelper;
@Override
public AjaxResult sendSmsCode(String mobile) {
// 产生6位随机验证码
String smsCode = StrUtils.getRandomString(6);
// 设置短信验证码的key
String key = "smsCode-" + mobile;
// 根据key从redis中获取短信验证码的value
String smsCodeByRedis = redisClient.get(key); //code:time
// 判断从redis中获取的短信验证码的值是否为空 // isBlank 等价于 str == null || str.length == 0 || str.trim().length == 0。
if (StringUtils.isNotBlank(smsCodeByRedis)) {
// 进入了if判断的方法体 说明redis中有验证码 // 校验是否已经过重发时间
// 使用字符串分割获取到redis中的短信验证码保存时候的时间戳
String recoredTime = smsCodeByRedis.split(":")[1];
// 使用字符串分割获取到redis中的短信验证码并赋值 //原来的短信验证码是合法的就用原来码
smsCode = smsCodeByRedis.split(":")[0];
// 判断用户从上次索取验证码到这次索取验证码的时间是否小于1分钟
if (new Date().getTime() - Long.valueOf(recoredTime) < 1 * 60 * 1000) {
// 当前时间-记录时间=间隔时间,如果小于1分钟说明没有过重发时间,返回false
return AjaxResult.me().setSuccess(false).setMessage("请不要频繁操作!");
}
}
// 把短信验证码存放到redis,并设置过期时间为5分钟。使用“smsCode-手机号”作为key,使用“短信验证码:当前时间戳”作为value,设置过期时间为5分钟
redisClient.set(key, smsCode + ":" + new Date().getTime(), 5 * 60);
// 发送短信验证码;
// smsHelper.sendSms(mobile,"1",new String[]{smsCode,"5"});
// 后台查看发送的验证码
System.out.println("已经向" + mobile + "发送了验证码:" + smsCode);
// 没有验证码-记录验证码
return AjaxResult.me();
}
}
2. 注册
就是给sso表,VipBase表添加一条数据而已!
3. 加密加盐保存密码和密码校验
package cn.wangningbo.hrm;
import cn.wangningbo.hrm.domain.Sso;
import cn.wangningbo.hrm.util.StrUtils;
import cn.wangningbo.hrm.util.encrypt.MD5;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = User9008Application.class)
public class PassMd5Test {
// 密码加密
@Test
public void testMd5() throws Exception {
// 使用自己封装的工具获取16位的随机盐值 // 这个随机盐值也要随着用户的信息保存到数据库中 以后用户登录要使用盐值进行密码比对!
String salt = StrUtils.getComplexRandomString(16);
// md5对密码进行加密 (密码+盐值)
String secretyPwd = MD5.getMD5("testPwd" + salt);
// 查看盐值
System.out.println(salt);
// 查看密码
System.out.println(secretyPwd);
}
//登录时比对,也就是把输入的秘密加密和数据库查询出来的进行比对
@Test
public void testLonginEqual() throws Exception {
String username = "xxx";
String pwd = "testPwd";
//模拟从数据库中通过用户名从数据库查询sso
Sso sso = new Sso();
// 模拟该用户专属的随机盐值
sso.setSalt("Qq7XiiDRCa8M0fGC");
// 模拟数据库中存储的加密后的密码
sso.setPassword("a87d151f6a908bd519a9b72482de9906");
// 使用MD5进行加密
String inputSecrutyPwd = MD5.getMD5(pwd + sso.getSalt());
// 判断数据库中存储的加密后的密码是否与用户传过来的加密后的密码是否相同
if (inputSecrutyPwd.equals(sso.getPassword())) {
System.out.println("登录成功!!!!!!!!!!!!!!!!!");
}
}
}