最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

短信+邮箱验证码登录

来源:博客园


(相关资料图)

1、新增依赖

    com.aliyun    aliyun-java-sdk-core    4.1.0    org.springframework.boot    spring-boot-starter-mail

2、前端示例

Login.vue
Login.vue
<script>import axios from "axios"export default {  name: "Login",  data() {    const validateUsername = (rule, value, callback) => {      if (value.length === 0) {        callback(new Error("请输入正确的用户名"))      } else {        callback()      }    }    const validatePassword = (rule, value, callback) => {      if (value.length < 6) {        callback(new Error("密码不能小于6位"))      } else {        callback()      }    }    const validatePhone = (rule, value, callback) => {      const reg = /^[1][3-9][0-9]{9}$/;      if (value == "" || value == undefined || value == null) {        callback(new Error("请输入手机号码"));      } else {        if ((!reg.test(value)) && value != "") {          callback(new Error("请输入正确的手机号码"));        } else {          callback();        }      }    }    return {      loginForm: {        username: "",        password: "",        key: "",        captcha: ""      },      phoneForm: {        phoneNo: "",        code: ""      },      emailForm: {        email: "",        code: ""      },      loginRules: {        username: [{required: true, trigger: "blur", validator: validateUsername}],        password: [{required: true, trigger: "blur", validator: validatePassword}],        phoneNo: [{required: true, trigger: "blur", validator: validatePhone}],        email: [{          required: true,          type: "email",          message: "请输入邮箱",          trigger: "blur"        }],        captcha: [{          required: true,          type: "string",          message: "请输入验证码",          trigger: "blur"        }],        code: [{          required: true,          type: "string",          message: "请输入验证码",          trigger: "blur"        }],        pwd: [{          required: true,          message: "创建密码",          trigger: "blur"        }, {pattern: /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,20}$/, message: "密码必须同时包含数字与字母,且长度为 8-20位"}],        cpwd: [{          required: true,          message: "确认密码",          trigger: "blur"        }, {          validator: (rule, value, callback) => {            if (value === "") {              callback(new Error("请再次输入密码"))            } else if (value !== this.ruleForm.pwd) {              callback(new Error("两次输入密码不一致"))            } else {              callback()            }          },          trigger: "blur"        }]      },      statusMsg: "",      loading: false,      isDisable: false,// 验证码按钮禁用      codeLoading: false,// 验证码loading      passwordType: "password",      redirect: undefined,      isRegist: true,      imageSrc: "",      verKey: "",      showDialog: false    }  },  watch: {    $route: {      handler: function (route) {        this.redirect = route.query && route.query.redirect      },      immediate: true    }  },  created() {    this.getCaptcha();  },  methods: {    /*获取验证码*/    getCaptcha() {      axios({        url: window.SITE_CONFIG["systemUrl"] + "/api/foreign/sms/get/captcha",        method: "get",        params: {}      }).then(res => {        console.log(res)        let result = res.data.data        this.loginForm.key = result.key;        this.imageSrc = result.image;      }).catch(err => {        console.log(err)      })    },    sendMsg: function (type) {      if (type === 1) {        const self = this        let phonePass        let timeRid        if (timeRid) {          return false        }        self.statusMsg = ""        this.$refs["phoneForm"].validateField("phoneNo", (valid) => {          phonePass = valid        })        // 向后台API验证码发送        if (!phonePass) {          self.codeLoading = true          self.statusMsg = "验证码发送中..."          let url = "";          let params = {};          axios({            url: window.SITE_CONFIG["systemUrl"] + "/api/foreign/sms/customer/sendMessageCode",            method: "get",            params: {phoneNo: self.phoneForm.phoneNo}          }).then(res => {            console.log(res)            let result = res.data            if (result.code == 200) {              this.$message({                showClose: true,                message: "发送成功,验证码有效期5分钟",                type: "success"              })              let count = 60              self.phoneForm.code = ""              self.codeLoading = false              self.isDisable = true              self.statusMsg = `验证码已发送,${count--}秒后重新发送`              timeRid = window.setInterval(function () {                self.statusMsg = `验证码已发送,${count--}秒后重新发送`                if (count <= 0) {                  window.clearInterval(timeRid)                  self.isDisable = false                  self.statusMsg = ""                }              }, 1000)            } else {              this.$message({                showClose: true,                message: result.data,                type: "warning"              })              this.isDisable = false              this.statusMsg = ""              this.codeLoading = false            }          }).catch(err => {            console.log(err)            this.isDisable = false            this.statusMsg = ""            this.codeLoading = false            console.log(err.data)          })        }      }      if (type === 2) {        const self = this        let emailPass        let timeRid        if (timeRid) {          return false        }        self.statusMsg = ""        this.$refs["emailForm"].validateField("email", (valid) => {          emailPass = valid        })        // 向后台API验证码发送        if (!emailPass) {          self.codeLoading = true          self.statusMsg = "验证码发送中..."          axios({            url: window.SITE_CONFIG["systemUrl"] + "/api/foreign/sms/customer/sendEmailMessage",            method: "get",            params: {email: self.emailForm.email}          }).then(res => {            console.log(res)            let result = res.data            if (result.code == 200) {              this.$message({                showClose: true,                message: "发送成功,验证码有效期5分钟",                type: "success"              })              let count = 60              self.emailForm.code = ""              self.codeLoading = false              self.isDisable = true              self.statusMsg = `验证码已发送,${count--}秒后重新发送`              timeRid = window.setInterval(function () {                self.statusMsg = `验证码已发送,${count--}秒后重新发送`                if (count <= 0) {                  window.clearInterval(timeRid)                  self.isDisable = false                  self.statusMsg = ""                }              }, 1000)            } else {              this.$message({                showClose: true,                message: result.data,                type: "warning"              })              this.isDisable = false              this.statusMsg = ""              this.codeLoading = false            }          }).catch(err => {            console.log(err)            this.isDisable = false            this.statusMsg = ""            this.codeLoading = false            console.log(err.data)          })        }      }    },    showPwd() {      if (this.passwordType === "password") {        this.passwordType = ""      } else {        this.passwordType = "password"      }      this.$nextTick(() => {        this.$refs.password.focus()      })    },    handleLogin() {      this.$refs.loginForm.validate(valid => {        if (valid) {          this.loading = true          this.show = false          this.$store.dispatch("user/login", this.loginForm).then(() => {            this.$router.push({path: "/"})            this.loading = false            this.show = true          }).catch(() => {            this.loading = false            this.show = true            this.getCaptcha()          })        } else {          console.log("操作异常")          this.getCaptcha()          return false        }      })    },    phoneLogin() {      this.$refs.phoneForm.validate(valid => {        if (valid) {          this.loading = true          this.show = false          this.$store.dispatch("user/phoneLogin", this.phoneForm).then(() => {            this.$router.push({path: "/"})            this.loading = false            this.show = true          }).catch(() => {            this.loading = false            this.show = true          })        } else {          console.log("操作异常")          return false        }      })    },    emailLogin() {      this.$refs.emailForm.validate(valid => {        if (valid) {          this.loading = true          this.show = false          this.$store.dispatch("user/emailLogin", this.emailForm).then(() => {            this.$router.push({path: "/"})            this.loading = false            this.show = true          }).catch(() => {            this.loading = false            this.show = true          })        } else {          console.log("操作异常")          return false        }      })    }  }}</script>

3、后端示例

SmsController
import io.swagger.annotations.ApiOperation;import org.springframework.web.bind.annotation.*;import javax.annotation.Resource;/** * 短信验证码 * * @author my */@RestController@CrossOrigin@RequestMapping("/api/foreign/sms")public class SmsController {    @Resource    private SmsService smsService;    /**     * 发送短信验证码     *     * @return     */    @ApiOperation(value = "发送短信验证码", httpMethod = "GET", notes = "发送短信验证码")    @GetMapping(value = "/customer/sendMessageCode")    public String sendSmsMessage(@RequestParam(value = "phoneNo") String phoneNo) {        return smsService.sendSmsMessage(phoneNo);    }    /**     * 发送邮箱验证码     *     * @return     */    @ApiOperation(value = "发送邮箱验证码", httpMethod = "GET", notes = "发送邮箱验证码")    @GetMapping(value = "/customer/sendEmailMessage")    public String sendEmailMessage(@RequestParam(value = "email") String email) {        return smsService.sendEmailMessage(email);    }    /**     * 获取验证码     *     * @return     */    @ApiOperation(value = "获取验证码", httpMethod = "GET", notes = "获取验证码")    @GetMapping(value = "/get/captcha")    public String captcha() {        return smsService.captcha();    }}
SmsService
import com.mxy.common.core.utils.DateUtils;import com.mxy.common.core.utils.RedisUtil;import com.mxy.common.core.utils.ServiceResult;import com.wf.captcha.SpecCaptcha;import org.apache.commons.lang3.StringUtils;import org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Service;import javax.annotation.Resource;import java.util.HashMap;import java.util.Map;import java.util.Random;import java.util.UUID;@Servicepublic class SmsService {    @Value("${sms.max.limit}")    private Integer maxLimit;    @Value("${sms.sendError.content}")    private String sendErrorContent;    @Resource    private RedisUtil redisUtil;    @Resource    private SmsSend smsSend;    private static final String MESSAGE_LIMIT = "messager_limit:";    private static final String SEND_LIMIT = "sendmsg_limit_count:";    private static final String PHONE_NO = "message_phone_no:";    private static final String EMAIL_MESSAGE_LIMIT = "email_messager_limit:";    private static final String EMAIL_SEND_LIMIT = "email_sendmsg_limit_count:";    private static final String EMAIL_NO = "message_email_no:";    private static final String CAPTCHA_NO = "message_captcha_no:";    private Random random = new Random();    public String sendSmsMessage(String phoneNo) {        // 非空检验        if (StringUtils.isEmpty(phoneNo)) {            return ServiceResult.error("电话号码不能为空哦");        }        String sendMsgKey = SEND_LIMIT + phoneNo;        if (redisUtil.hasKey(sendMsgKey) && (int) redisUtil.get(sendMsgKey) > maxLimit) {            return ServiceResult.error(sendErrorContent);        }        String phoneNoKey = PHONE_NO + phoneNo;        // 如果验证码已发送 作废之前的验证码        if (redisUtil.hasKey(phoneNoKey)) {            redisUtil.del(phoneNoKey);        }        String limitKey = MESSAGE_LIMIT + phoneNo;        if (redisUtil.hasKey(limitKey)) {            return ServiceResult.error("一分钟只能请求一次哦");        }        // 随机生成6位验证码        String verifyCode = String.valueOf(random.nextInt(899999) + 100000);        // 限制60秒只能生成一次验证码        redisUtil.set(limitKey, verifyCode, 60);        // 短信验证码 5分钟失效        redisUtil.set(phoneNoKey, verifyCode, 300);        int count = (int) (redisUtil.get(sendMsgKey) == null ? 0 : redisUtil.get(sendMsgKey));        // 计算当天23点59分59秒的秒数        long expireTime = DateUtils.getDifferentTimes();        // 当日0点过期        redisUtil.set(sendMsgKey, count + 1, expireTime);        // 异步请求下发短信        smsSend.sendSmsMessage(phoneNo, verifyCode, 2);        return ServiceResult.success("短信发送成功");    }    public String sendEmailMessage(String email) {        // 非空检验        if (StringUtils.isEmpty(email)) {            return ServiceResult.error("邮箱地址不能为空哦");        }        String sendMsgKey = EMAIL_SEND_LIMIT + email;        if (redisUtil.hasKey(sendMsgKey) && (int) redisUtil.get(sendMsgKey) > maxLimit) {            return ServiceResult.error(sendErrorContent);        }        String emailNoKey = EMAIL_NO + email;        // 如果验证码已发送 作废之前的验证码        if (redisUtil.hasKey(emailNoKey)) {            redisUtil.del(emailNoKey);        }        String limitKey = EMAIL_MESSAGE_LIMIT + email;        if (redisUtil.hasKey(limitKey)) {            return ServiceResult.error("一分钟只能请求一次哦");        }        // 随机生成6位验证码        String verifyCode = String.valueOf(random.nextInt(899999) + 100000);        // 限制60秒只能生成一次验证码        redisUtil.set(limitKey, verifyCode, 60);        // 短信验证码 5分钟失效        redisUtil.set(emailNoKey, verifyCode, 300);        int count = (int) (redisUtil.get(sendMsgKey) == null ? 0 : redisUtil.get(sendMsgKey));        // 计算当天23点59分59秒的秒数        long expireTime = DateUtils.getDifferentTimes();        // 当日0点过期        redisUtil.set(sendMsgKey, count + 1, expireTime);        // 异步请求下发邮件        smsSend.sendEmailMessage(email, verifyCode);        return ServiceResult.success("邮件发送成功");    }    public String captcha() {        SpecCaptcha specCaptcha = new SpecCaptcha(130, 48, 4);        String verCode = specCaptcha.text().toLowerCase();        String key = UUID.randomUUID().toString();        // 存入redis并设置过期时间为300秒        redisUtil.set(CAPTCHA_NO + key, verCode, 300);        // 将key和base64返回给前端        Map map = new HashMap<>();        map.put("key", key);        map.put("image", specCaptcha.toBase64());        return ServiceResult.success(map);    }}
SmsSend
import com.aliyuncs.CommonRequest;import com.aliyuncs.CommonResponse;import com.aliyuncs.DefaultAcsClient;import com.aliyuncs.IAcsClient;import com.aliyuncs.profile.DefaultProfile;import com.mxy.common.core.entity.SysSmsSendLog;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Value;import org.springframework.mail.MailException;import org.springframework.mail.SimpleMailMessage;import org.springframework.mail.javamail.JavaMailSender;import org.springframework.scheduling.annotation.Async;import org.springframework.stereotype.Component;import javax.annotation.Resource;/** * 短信发送 * * @author my */@Slf4j@Componentpublic class SmsSend {    @Value("${sms.accessKeyId}")    private String accessKeyId;    @Value("${sms.secret}")    private String secret;    @Resource    private JavaMailSender sender;    /**     * @description: 短信验证码发送     * @param: phoneNo-接收号码、verifyCode-验证码、type-短信模板类型(默认通用模板)(1-注册、2-登录、0-通用)     * 签名说明:     * 个人日常博客     * 模板说明:     * 通用模板:SMS_25073XXXX   您的验证码${code},该验证码5分钟内有效,请勿泄漏于他人!     * 登录验证码模板:SMS_25073XXXX    验证码为:${code},您正在登录,若非本人操作,请勿泄露。     * 注册验证码模板:SMS_25075XXXX    您正在申请手机注册,验证码为:${code},5分钟内有效!     **/    @Async("threadPoolTaskExecutor")    public void sendSmsMessage(String phoneNo, String verifyCode, int type) {        DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou",                accessKeyId, secret);        IAcsClient client = new DefaultAcsClient(profile);        // 组装请求对象        CommonRequest request = new CommonRequest();        // 短信API产品域名(接口地址固定,无需修改)        request.setDomain("dysmsapi.aliyuncs.com");        request.setVersion("2017-05-25");        request.setAction("SendSms");        request.putQueryParameter("RegionId", "cn-hangzhou");        // 接收号码        request.putQueryParameter("PhoneNumbers", phoneNo);        // 短信签名        request.putQueryParameter("SignName", "个人日常博客");        // 短信模板        String smsTemplate = "";        switch (type) {            case 1:                request.putQueryParameter("TemplateCode", "SMS_25075XXXX");                smsTemplate = "【个人日常博客】您正在申请手机注册,验证码为:" + verifyCode + ",5分钟内有效!";                break;            case 2:                request.putQueryParameter("TemplateCode", "SMS_25073XXXX");                smsTemplate = "【个人日常博客】验证码为:" + verifyCode + ",您正在登录,若非本人操作,请勿泄露。";                break;            default:                request.putQueryParameter("TemplateCode", "SMS_25073XXXX");                smsTemplate = "【个人日常博客】您的验证码" + verifyCode + ",该验证码5分钟内有效,请勿泄漏于他人!";                break;        }        // 验证码        request.putQueryParameter("TemplateParam", "{code:" + verifyCode + "}");        try {            CommonResponse response = client.getCommonResponse(request);            // 记录发送记录,可忽略            SysSmsSendLog sendLog = new SysSmsSendLog();            sendLog.setPhone(phoneNo);            sendLog.setRequest(smsTemplate);            sendLog.setResponse(String.valueOf(response.getData()));            sendLog.insert();            log.info(phoneNo + "短信发送:" + response.getData());        } catch (Exception e) {            e.printStackTrace();            log.info(phoneNo + "短信发送失败:" + e.getMessage());        }    }    @Async("threadPoolTaskExecutor")    public void sendEmailMessage(String email, String verifyCode) {        try {            SimpleMailMessage mailMessage = new SimpleMailMessage();            mailMessage.setFrom("you.email@qq.com");            mailMessage.setTo(email);            mailMessage.setSubject("个人日常博客验证码");            mailMessage.setText("您的验证码" + verifyCode + ",该验证码5分钟内有效,请勿泄漏于他人!");            sender.send(mailMessage);            SysSmsSendLog sendLog = new SysSmsSendLog();            sendLog.setPhone(email);            sendLog.setRequest(mailMessage.getText());            sendLog.setResponse("OK");            log.info(email + "->邮件发送:" + mailMessage.getText());            sendLog.insert();        } catch (MailException e) {            e.printStackTrace();            log.info(email + "邮件发送失败:" + e.getMessage());        }    }}

工具类

DateUtils
/**     * 计算当天23点59分59秒的秒数     */    public static Long getDifferentTimes() {        //计算当前时间到0点的秒数        Calendar cal = Calendar.getInstance();        cal.add(Calendar.DAY_OF_YEAR, 1);        cal.set(Calendar.HOUR_OF_DAY, 0);        cal.set(Calendar.SECOND, 0);        cal.set(Calendar.MINUTE, 0);        cal.set(Calendar.MILLISECOND, 0);        return (cal.getTimeInMillis() - System.currentTimeMillis()) / 1000;    }
RedisUtil
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.stereotype.Component;import org.springframework.util.CollectionUtils;import java.util.List;import java.util.Map;import java.util.Set;import java.util.concurrent.TimeUnit;/** * Redis工具类 * * @author my * @date 2022-02-10 */@Componentpublic final class RedisUtil {    @Autowired    private RedisTemplate redisTemplate;    /**     * 判断key是否存在     *     * @param key 键     * @return true 存在 false不存在     */    public boolean hasKey(String key) {        try {            return redisTemplate.hasKey(key);        } catch (Exception e) {            e.printStackTrace();            return false;        }    }    /**     * 普通缓存获取     *     * @param key 键     * @return 值     */    public Object get(String key) {        return key == null ? null : redisTemplate.opsForValue().get(key);    }    /**     * 普通缓存放入     *     * @param key   键     * @param value 值     * @return true成功 false失败     */    public boolean set(String key, Object value) {        try {            redisTemplate.opsForValue().set(key, value);            return true;        } catch (Exception e) {            e.printStackTrace();            return false;        }    }    /**     * 普通缓存放入并设置时间     *     * @param key   键     * @param value 值     * @param time  时间(秒) time要大于0 如果time小于等于0 将设置无限期     * @return true成功 false 失败     */    public boolean set(String key, Object value, long time) {        try {            if (time > 0) {                redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);            } else {                set(key, value);            }            return true;        } catch (Exception e) {            e.printStackTrace();            return false;        }    }    /**     * 删除缓存     *     * @param key 可以传一个值 或多个     */    @SuppressWarnings("unchecked")    public void del(String... key) {        if (key != null && key.length > 0) {            if (key.length == 1) {                redisTemplate.delete(key[0]);            } else {                redisTemplate.delete(CollectionUtils.arrayToList(key));            }        }    }}

配置文件

application.yml
# 配置-emailspring:  mail:    host: smtp.qq.com  # 发送邮件的服务器地址    username: you.email@qq.com # 开启 IMAP/SMTP服务 的qq邮箱的账号    password: xxxxxxxxxxxx  # 开启 IMAP/SMTP服务 获得的授权码    default-encoding: UTF-8# 阿里云短信秘钥sms:  accessKeyId: xxxxxxxxxxxx  secret: xxxxxxxxxxxx  max:    limit: 10  sendError:    content: 当日的获取验证码次数已用尽,请联系管理员解除限制。

关键词: 请输入验证码 邮件发送