一. MD5加密工具类
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* 密码加密工具
*/
public class Md5Utils {
/**
* 加密
* @param context
*/
public static String encrypByMd5(String context) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(context.getBytes());//update处理
byte [] encryContext = md.digest();//调用该方法完成计算
int i;
StringBuffer buf = new StringBuffer("");
for (int offset = 0; offset < encryContext.length; offset++) {//做相应的转化(十六进制)
i = encryContext[offset];
if (i < 0) i += 256;
if (i < 16) buf.append("0");
buf.append(Integer.toHexString(i));
}
return buf.toString();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
}
二. 短信服务
短信验证,只有三大运营商具有短信发送的能力。要发送短信只有找三大运营,或者中间商。简单说就是要找第三方的短信平台。常见的有阿里云,京东智联云,乐讯通等等非常多。举例使用网建短信通:http://www.smschinese.cn/
操作流程
点击左上角首页 -> API接口 -> 网建SMS短信通API接口地址 -> UTF-8编码发送短信接口: http://utf8.api.smschinese.cn/?Uid=本站用户名&Key=接口短信密钥&smsMob=手机号码&smsText=验证码:8888 本站用户名Uid:注册时用户名 接口安全密钥key:刚刚看到的密钥 手机号码smsMob:手机号码 短信内容smsText:随便写 api接口中有发送短信的各个对应状态:发送了一条,就只剩下4条了
导入依赖
<!-- 主要用于后端发送http请求--> <!-- 后端发送http请求 - 一般用在调用三方接口时会用 --> <dependency> <groupId>commons-httpclient</groupId> <artifactId>commons-httpclient</artifactId> <version>3.1</version> </dependency>
发送短信工具类(官网也有相应代码可参考)
package io.coderyeah.basic.util; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.NameValuePair; import org.apache.commons.httpclient.methods.PostMethod; /** * 短信发送工具类 */ public class SmsUtils { //用户名 public static final String UID = "codermyth"; //秘钥 public static final String KEY = "29766C0677741B5DA2CE2203260365DB"; /** * 发送短信 * * @param phones 手机们 a,b * @param content 发送内容 * @return 返回值 */ public static String sendSms(String phones, String content) { PostMethod post = null; try { HttpClient client = new HttpClient(); post = new PostMethod("http://utf8.api.smschinese.cn"); post.addRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf8");//在头文件中设置转码 NameValuePair[] data = {new NameValuePair("Uid", SmsUtils.UID), new NameValuePair("Key", SmsUtils.KEY), new NameValuePair("smsMob", phones), new NameValuePair("smsText", content)}; post.setRequestBody(data); client.executeMethod(post); int statusCode = post.getStatusCode(); System.out.println("statusCode:" + statusCode); //200 404 400 String result = new String(post.getResponseBodyAsString().getBytes("utf8")); return result; } catch (Exception e) { e.printStackTrace(); } finally { if (post != null) { post.releaseConnection(); } } return null; } public static void main(String[] args) { System.out.println(SmsUtils.sendSms("18365403510", "您的验证码为:【8848】,鉴于您优秀的能力表现,您被授予玛丽叶奥特曼称号,accept it, cutie!")); } }
三. 前端获取验证码接口
<div class="verification">
<label for="code"><i class="am-icon-code-fork"></i></label>
<input type="tel" name="" id="code" v-model="phoneUserForm.phoneCode" placeholder="请输入验证码">
<button type="button" id="dyMobileButton" @click="sendMobileCode">获取验证码</button>
</div>
获取短信验证码
// 发送验证码
sendMobileCode() {
//1.判断手机号不为空
if (!this.phoneUserForm.phone) {
alert("手机号不能为空");
return;
}
//2.判断图片验证码不为空
if (!this.phoneUserForm.imageCode) {
alert("图片验证码不能为空");
return;
}
//3.获取按钮,禁用按钮 发送时灰化不能使用,发送成功倒计时60才能使用,如果发送失败立即可以发送
let sendBtn = $(event.target);
sendBtn.attr("disabled", true);
let param = {
phone: this.phoneUserForm.phone,
imageCode: this.phoneUserForm.imageCode,
imageCodeKey: localStorage.getItem("verifyCodeKey")
};
//4.发送ajax请求
this.$http.post("/verifyCode/smsCode", param).then(res => {
const ajaxResult = res.data;
if (ajaxResult.success) {
alert("手机验证码已经发送到您的手机,请在3分钟内使用");
//4.1.发送成:倒计时
let time = 60;
let interval = window.setInterval(function () {
//每一条倒计时减一
time = time - 1;
//把倒计时时间搞到按钮上
sendBtn.html(time + 's');
//4.2.倒计时完成恢复按钮
if (time <= 0) {
sendBtn.html("重新发送");
sendBtn.attr("disabled", false);
//清除定时器
window.clearInterval(interval);
}
}, 1000);
} else {
//4.3.发送失败:提示,恢复按钮
sendBtn.attr("disabled", false);
alert(ajaxResult.msg);
}
})
}
发送请求
//手机注册功能
phoneRegister() {
if (!this.agree) {
alert('请勾选服务协议')
return;
}
//前台一般做校验:空校验,格式校验,重复密码校验
this.$http.post('/user/register/phone', this.phoneUserForm).then(res => {
//注册成功跳转到登录页面
if (res.data.success) {
location.href = "login.html";
} else {
alert(res.data.msg);
}
}).catch(res => {
alert("系统错误!")
});
},
四. 后端实现获取短信接口
@PostMapping("/smsCode")
@ApiOperation("获取短信验证码")
public Result getPhoneCode(@RequestBody PhoneCodeDTO phoneCodeDTO) {
try {
return verifyCodeService.getPhoneCode(phoneCodeDTO);
} catch (BusinessException e) {
e.printStackTrace();
return Result.fail(e.getMessage());
} catch (Exception e) {
return Result.fail("系统异常,请稍后重试!");
}
}
@Override
public Result getPhoneCode(PhoneCodeDTO phoneCodeDTO) {
final String phone = phoneCodeDTO.getPhone();
final String InputImageCode = phoneCodeDTO.getImageCode();
final String imageCodeKey = phoneCodeDTO.getImageCodeKey();
// 1.判断参数是否为空
if (StrUtil.isBlank(phone)) {
// 抛出异常
throw new BusinessException("电话号码不能为空");
}
if (StrUtil.isBlank(InputImageCode)) {
// 抛出异常
throw new BusinessException("图形验证码不能为空不能为空");
}
// 2.判断图形验证码是否过期 正确
final String imageCode = stringRedisTemplate.opsForValue().get("cache:code:image:" + imageCodeKey);
if (StrUtil.isBlank(imageCode)) {
// 过期了
throw new BusinessException("图形验证码已过期,请重新输入!");
}
// 判断是否一致 忽略大小写
if (!InputImageCode.equalsIgnoreCase(imageCode)) {
throw new BusinessException("图片验证码错误,请重新输入!");
}
// 3. 通过号码判断用户是否已经注册
final User user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getPhone, phone));
if (user != null) {
// 用户已经存在
throw new BusinessException("该手机号码已被注册过,请您直接登录...");
}
// 4.从redis获取短信验证码
// 用来存储短信验证码 redis中存储的值是 【短信验证码:时间戳】
String code = null;
final String value = stringRedisTemplate.opsForValue().get(Constants.USER_REGISTER_PHONE_PREFIX + phone);
if (value != null) { // 没有过期
// 判断时间是否过期
final long oldTime = Long.parseLong(value.split(":")[1]);
// 一分钟之内不允许频繁操作
if ((System.currentTimeMillis() - oldTime) <= 1000 * 60) {// 没过重发时间
throw new BusinessException("操作频繁,请稍后再试!");
} else {
code = value.split(":")[0];
}
} else {// 过期了
// 生成验证码
code = String.valueOf(RandomUtil.randomNumbers(6));
}
// 存入redis 有效期3分钟
stringRedisTemplate.opsForValue().set("user:register:" + phone, code + ":" + System.currentTimeMillis(), 3L, TimeUnit.MINUTES);
// 发送验证码短信
// SmsUtils.sendSms(phone, "您的验证码是" + code + ",请及时使用有限期为3分钟");
log.info("=========您的验证码是:{}=========", code);
return Result.success("获取验证码成功【" + code + "】");
}