短信服务:
网课里使用阿里云的短信服务,但现在阿里云个人申请有点麻烦,本文关于短信仅作步骤展示
注册阿里云账号:
阿里云:阿里云-为了无法计算的价值 (aliyun.com)
申请短信签名:
短信签名时短信发送者的署名,表示发送方的身份,如【菜鸟驿站】,【CSDN】
设置短信模板:
模板包括短信发送的类型、内容、CODE等
设置AccessKey:
AccessKey是程序访问阿里云API的密钥,具有对应账户的完全权限
出于安全考虑,使用子用户AccessKey,权限受限
AccessKey ID:类似用户名
AccessKey Secret:类似密码
为子用户设置SMS权限
编码实现
邮箱服务:
通过发送邮件实现验证码登录
导入依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
参考:(2条消息) Springboot实现发送邮件功能_spring boot 发送邮件_12程序猿的博客-CSDN博客
(2条消息) SpringBoot 发送电子邮件_spring boot 发送电子邮件_Nice2cu_Code的博客-CSDN博客
创建User的mapper, service, serviceImpl, controller
导入生成验证码工具类ValidateCodeUtils:
\瑞吉外卖-资料\1 瑞吉外卖项目\1 瑞吉外卖项目\资料\工具类\ValidateCodeUtils.java
修改前端代码:
这里需要注意:资料给的前端代码是有问题的,前端自动生成验证码,而不是发送请求给后端,所以我们需要把原先的/front文件夹中的所有文件替换为\瑞吉外卖-资料\1 瑞吉外卖项目\1 瑞吉外卖项目\代码\day05\reggie_take_out\reggie_take_out\src\main\resources\front 里的文件
为了便于理解,我们将发送的/user/sendMsg请求改为/user/sendMail
// login.js
function sendMsgApi(data) {
return $axios({
'url': '/user/sendMail',
'method': 'post',
data
})
}
然后修改一下页面,把手机号改为邮箱地址
根据参考文章修改application.yml文件
这里需要提前声明一下,我不打算修改实体类User的phone属性名,因为前端已经定义好“phone”了,而且也懒得修改数据库中字段了,所以此后还会不时出现“phone”
添加过滤路径:
// LoginCheckFilter.java
String[] urls = {
"/employee/login",
"/employee/logout",
"/backend/**",
"/front/**",
"/user/sendMail",
"/user/login"
};
测试前记得maven clean一下,否则页面显示Whitelabel Error Page
增加移动端的登录状态检测:
// LoginCheckFilter.java
...
// 进入if的是已登录的,放过(PC端)
Long empId = (Long) request.getSession().getAttribute("employee");
if (empId != null){
BaseContext.setCurrentId(empId);
filterChain.doFilter(request, response);
return ;
}
// 进入if的是已登录的,放过(移动端)
Long userId = (Long)request.getSession().getAttribute("user");
if (userId != null){
BaseContext.setCurrentId(userId);
filterChain.doFilter(request, response);
return ;
}
...
添加Mail服务类:
package com.falling.reggie.service.impl;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import javax.mail.MessagingException;
import java.util.Date;
@Service
public class MailService {
private static final Logger logger = LoggerFactory.getLogger(MailService.class);
/**
* 注入邮件工具类
*/
@Autowired
private JavaMailSenderImpl javaMailSender;
@Value("${spring.mail.username}")
private String sendMailer;
/**
* 检测邮件信息类
* @param to
* @param subject
* @param text
*/
private void checkMail(String to,String subject,String text){
if(StringUtils.isEmpty(to)){
throw new RuntimeException("邮件收信人不能为空");
}
if(StringUtils.isEmpty(subject)){
throw new RuntimeException("邮件主题不能为空");
}
if(StringUtils.isEmpty(text)){
throw new RuntimeException("邮件内容不能为空");
}
}
/**
* 发送纯文本邮件
* @param to
* @param subject
* @param text
*/
public void sendTextMailMessage(String to,String subject,String text){
try {
//true 代表支持复杂的类型
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(javaMailSender.createMimeMessage(),true);
//邮件发信人
mimeMessageHelper.setFrom(sendMailer);
//邮件收信人 1或多个
mimeMessageHelper.setTo(to.split(","));
//邮件主题
mimeMessageHelper.setSubject(subject);
//邮件内容
mimeMessageHelper.setText(text);
//邮件发送时间
mimeMessageHelper.setSentDate(new Date());
//发送邮件
javaMailSender.send(mimeMessageHelper.getMimeMessage());
System.out.println("发送邮件成功:"+sendMailer+"->"+to);
} catch (MessagingException e) {
e.printStackTrace();
System.out.println("发送邮件失败:"+e.getMessage());
}
}
}
发送邮件:
// UserController.java
@PostMapping("/sendMail")
public R<String> sendMail(@RequestBody User user, HttpSession session){
String mailAds = user.getPhone();
// 生成验证码
String code = ValidateCodeUtils.generateValidateCode4String(4);
log.info("code = {}", code);
String text = (user.getName() == null ? "新用户" : user.getName()) + "您好,\n您本次登录的验证码为:"+code;
mailService.sendTextMailMessage(mailAds, "瑞吉外卖 验证码", text);
// 保存验证码,用于检验用户输入的是否正确
session.setAttribute(mailAds, code);
return R.success("send mail success...");
}
登录校验:
// UserController.java
@PostMapping("/login")
// 这里使用Map来接收code和mailAds
public R<User> login(@RequestBody Map<String, String> map, HttpSession session){
String mailAds = map.get("phone");
String code = map.get("code");
// 获取发出的code
String codeInSession = session.getAttribute(mailAds).toString();
// 比对
if (codeInSession != null && codeInSession.equals(code)){
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(User::getPhone, mailAds);
User user = userService.getOne(queryWrapper);
boolean save = false;
// 数据库里没查到,是新用户
if (user == null){
user = new User();
user.setPhone(mailAds);
user.setStatus(1);
// 保存新用户
save = userService.save(user);
}
// 登录成功,保存userId到session
session.setAttribute("user", user.getId());
return R.success(user);
}
return R.error("login fail...");
}