瑞吉外卖 qq邮箱实现验证码登录
获得 SMTP 授权码
qfxcuawmuysigfaj
添加依赖
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>3.3.1</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
配置yml
mail:
host: smtp.qq.com
username: 1102124756@qq.com
password: qfxcuawmuysigfaj
port: 587
default-encoding: UTF-8
properties:
mail:
smtp:
socketFactoryClass: javax.net.ssl.SSLSocketFactory
# 开启debug以后,邮件发送过程的日志会在控制台上打印出来
debug: true
拦截器放行
/**
* 检查用户是否已经完成登录
*/
@WebFilter(filterName = "loginCheckFilter",urlPatterns = "/*")
@Slf4j
public class LoginCheckFilter implements Filter{
//路径匹配器,支持通配符
public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
//1、获取本次请求的URI
String requestURI = request.getRequestURI();// /backend/index.html
log.info("拦截到请求:{}",requestURI);
//定义不需要处理的请求路径
String[] urls = new String[]{
"/employee/login",
"/employee/logout",
"/backend/**",
"/front/**",
"/common/**",
"/user/sendMsg",
"/user/login"
};
//2、判断本次请求是否需要处理
boolean check = check(urls, requestURI);
//3、如果不需要处理,则直接放行
if(check){
log.info("本次请求{}不需要处理",requestURI);
filterChain.doFilter(request,response);
return;
}
//4-1、判断登录状态,如果已登录,则直接放行
if(request.getSession().getAttribute("employee") != null){
log.info("用户已登录,用户id为:{}",request.getSession().getAttribute("employee"));
Long empId = (Long) request.getSession().getAttribute("employee");
BaseContext.setCurrentId(empId);
filterChain.doFilter(request,response);
return;
}
//4-2、判断登录状态,如果已登录,则直接放行
if(request.getSession().getAttribute("user") != null){
log.info("用户已登录,用户id为:{}",request.getSession().getAttribute("user"));
Long userId = (Long) request.getSession().getAttribute("user");
BaseContext.setCurrentId(userId);
filterChain.doFilter(request,response);
return;
}
log.info("用户未登录");
//5、如果未登录则返回未登录结果,通过输出流方式向客户端页面响应数据
response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));
}
/**
* 路径匹配,检查本次请求是否需要放行
* @param urls
* @param requestURI
* @return
*/
public boolean check(String[] urls,String requestURI){
for (String url : urls) {
boolean match = PATH_MATCHER.match(url, requestURI);
if(match){
return true;
}
}
return false;
}
}
编写 Controller
@RestController
@Slf4j
@RequestMapping("/user")
public class UserController {
@Resource
UserService userService;
@Resource
JavaMailSender javaMailSender;
@Value("${spring.mail.username}")
String from;
@PostMapping("/sendMsg")
private R<String> sendMsg(@RequestBody User user, HttpSession session) {
// 这里用qq邮箱去发送验证码
//获取到前端提交过来的qq号
String phone = user.getPhone();
//这里工具类判是否为空
if (StringUtils.isNotEmpty(phone)) {
// 这里用到生成验证码的工具类
String code = ValidateCodeUtils.generateValidateCode(4).toString();//生成四位的验证码
log.info("code={}", code);
// 构建一个邮件的对象
SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
// 设置邮件发件者
simpleMailMessage.setFrom(from);
// 设置邮件接受者
simpleMailMessage.setTo(phone);
// 设置有纪念的主题
simpleMailMessage.setSubject("登录验证码");
// 设置邮件的征文
String text = "[瑞吉外卖] 您的验证码为" + code + "请勿泄露";
simpleMailMessage.setText(text);
//将生成的验证码保存到Session
// 将我们生成的手机号和验证码放到session里面,我们后面用户填入验证码之后,我们验证的时候就从这里去取然后进行比对
//这里我们需要一个异常捕获
session.setAttribute(phone, code);
// return R.success("手机验证码短信发送成功");
try {
javaMailSender.send(simpleMailMessage);
return R.success("手机验证码短信发送成功");
} catch (MailException e) {
e.printStackTrace();
}
}
return R.error("手机验证码发送失败");
}
// 移动应用登录端
@PostMapping("/login")
// 这里使用map来接收前端传过来的值
private R<User> login(@RequestBody Map map, HttpSession session) {
log.info(map.toString());
// 使用map来接收参数,接收键值参数、
// 编写处理逻辑
// 获取到手机号
// 获取到验证码
// 从Session中获取到保存的验证码
// 将session中获取到的验证码和前端提交过来的验证码进行比较,这样就可以实现一个验证的方式
// 比对页面提交的验证码和session中
//判断当前的手机号在数据库查询是否有记录,如果没有记录,说明是一个新的用户,然后自动将这个手机号进行注册
String phone = map.get("phone").toString();
String code = map.get("code").toString();
//获取session中phone字段对应的验证码
Object codeInSession = session.getAttribute(phone);
// 下面进行比对
if (codeInSession != null && codeInSession.equals(code)) {
LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
// 在表中根据号码来查询是否存在该邮箱用户
userLambdaQueryWrapper.eq(User::getPhone, phone);
User user = userService.getOne(userLambdaQueryWrapper);
if (user == null) {
//判断当前手机号对应的用户是否为新用户,如果是新用户就自动完成注册
user = new User();
user.setPhone(phone);
user.setStatus(1);
userService.save(user);
}
// 这里我们将user存储进去,后面各项操作,我们会用,其中拦截器那边会判断用户是否登录,所以我们将这个存储进去,
session.setAttribute("user", user.getId());
return R.success(user);
}
return R.error("验证失败");
}
/**
* 退出登录
*
* @param session
* @return
*/
@PostMapping("/loginout")
public R<String> loginout(HttpSession session) {
//清除session中的id。
session.removeAttribute("user");
return R.success("退出登录成功");
}
}