发送邮箱验证码功能及邮箱密码登录功能

pull/2/head
2991692032 2 months ago
parent 98c9cd64b9
commit f8cd2a11f8

@ -49,6 +49,12 @@
<artifactId>hutool-all</artifactId>
<version>5.8.16</version>
</dependency>
<!-- redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 邮箱服务-->
<dependency>
<groupId>org.springframework.boot</groupId>

@ -0,0 +1,7 @@
package com.unilife.common.constant;
public class RedisConstant {
public static final String LOGIN_EMAIL_KEY="login:email:";
public static final String LOGIN_EMAIL_LIMIT_KEY = "login:email:limit:";
}

@ -4,6 +4,7 @@ import com.unilife.common.result.Result;
import com.unilife.model.dto.EmailDTO;
import com.unilife.model.dto.LogDTO;
import com.unilife.model.dto.LoginDTO;
import com.unilife.model.dto.LoginEmailDTO;
import com.unilife.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@ -42,5 +43,10 @@ public class UserController {
return userService.sendVerificationCode(email);
}
@ApiOperation(value = "邮箱验证码登录")
@PostMapping("login/code")
public Result loginWithEmailCode(@RequestBody LoginEmailDTO loginEmailDTO){
return userService.loginWithEmail(loginEmailDTO);
}
}

@ -8,4 +8,5 @@ import org.apache.ibatis.annotations.Param;
public interface UserMapper {
void insert(User user);
User FindByEmail(@Param("email") String email, @Param("password") String password);
User getUserByEmail(String email);
}

@ -0,0 +1,13 @@
package com.unilife.model.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class LoginEmailDTO {
private String email;
private String code;
}

@ -3,7 +3,7 @@ package com.unilife.service;
import com.unilife.common.result.Result;
import com.unilife.model.dto.LogDTO;
import com.unilife.model.dto.LoginDTO;
import com.unilife.model.entity.User;
import com.unilife.model.dto.LoginEmailDTO;
public interface UserService {
@ -11,4 +11,8 @@ public interface UserService {
Result login(LogDTO logDTO);
Result sendVerificationCode(String email);
Result loginWithEmail(LoginEmailDTO loginEmailDTO);
}

@ -2,10 +2,13 @@ package com.unilife.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.unilife.common.constant.RedisConstant;
import com.unilife.common.result.Result;
import com.unilife.mapper.UserMapper;
import com.unilife.model.dto.LogDTO;
import com.unilife.model.dto.LoginDTO;
import com.unilife.model.dto.LoginEmailDTO;
import com.unilife.model.entity.User;
import com.unilife.model.vo.LogVO;
import com.unilife.model.vo.LoginVO;
@ -14,6 +17,7 @@ import com.unilife.utils.RegexUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
@ -22,6 +26,13 @@ import org.springframework.stereotype.Service;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import static com.unilife.common.constant.RedisConstant.LOGIN_EMAIL_KEY;
@Slf4j
@Component
@Service
@ -33,9 +44,15 @@ public class UserServiceImpl implements UserService {
@Autowired
private JavaMailSender mailSender;
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Value("${spring.mail.username}")
private String from;
final int CODE_EXPIRE_MINUTES = 10;
final int LIMIT_SECONDS=60;
@Override
@ -76,14 +93,25 @@ public class UserServiceImpl implements UserService {
return Result.error(400,"邮箱格式不正确");
}
//2.生成随机验证码
String code = RandomUtil.randomNumbers(6);
log.debug("成功生成验证码,邮箱{},验证码{}", email, code);
//2.防止频繁发送验证码
String countKey = RedisConstant.LOGIN_EMAIL_LIMIT_KEY + email;
Boolean setSuccess = stringRedisTemplate.opsForValue().setIfAbsent(
countKey,
"1",
Duration.ofSeconds(LIMIT_SECONDS)
);
if (Boolean.FALSE.equals(setSuccess)) {
return Result.error(null, "请求过于频繁,请稍后再试");
}
//3.生成随机验证码
String code = RandomUtil.randomNumbers(6);
log.debug("成功生成验证码,邮箱{},验证码{}", email, code);
//3.发送验证码到邮箱
//4.发送验证码到邮箱
try {
//构建邮件
MimeMessage message=mailSender.createMimeMessage();
@ -115,12 +143,78 @@ public class UserServiceImpl implements UserService {
}
//4.存储随机产生的验证码
//5.存储随机产生的验证码,设置有效期为十分钟
stringRedisTemplate.opsForValue().set(LOGIN_EMAIL_KEY + email, code, Duration.ofMinutes(CODE_EXPIRE_MINUTES));
return Result.success(200,"验证码已发送");
}
@Override
public Result loginWithEmail(LoginEmailDTO loginEmailDTO) {
String email=loginEmailDTO.getEmail();
if(RegexUtils.isEmailInvalid(email)){
return Result.error(null,"请输入正确的邮箱");
}
String cacheCode = stringRedisTemplate.opsForValue().get(RedisConstant.LOGIN_EMAIL_KEY + email);
if (cacheCode == null) {
return Result.error(null, "验证码已过期或未发送,请重新获取");
}
// 3. 校验验证码是否正确
String code = loginEmailDTO.getCode();
if (!cacheCode.equals(code)) {
return Result.error(null, "验证码错误");
}
// 4. 验证通过,删除验证码
stringRedisTemplate.delete(RedisConstant.LOGIN_EMAIL_KEY + email);
// 5. 查询用户是否存在
User user=userMapper.getUserByEmail(email);
if(user == null){
user=createUserWithEmail(email);
}
//6.生成登录凭证
//TODO
// 8. 返回用户信息和登录凭证
Map<String, Object> userInfo = new HashMap<>();
//HashMap userInfo.put("token", token);
userInfo.put("user", user);
return Result.success(200,"验证码已发送");
return Result.success(userInfo);
}
/**
* 使
*/
private User createUserWithEmail(String email) {
User user = new User();
user.setEmail(email);
user.setNickname("用户" + RandomUtil.randomString(6)); // 生成随机昵称
String username = email.split("@")[0]+"_"+ RandomUtil.randomString(4); // 使用@前面的部分作为用户名
user.setUsername(username);
String password=RandomUtil.randomString(6);
user.setPassword(password);
user.setRole((byte)0); // 普通用户角色
user.setStatus((byte)1); // 正常状态
user.setIsVerified((byte)0); // 未验证
user.setPoints(0); // 初始积分
user.setGender((byte)0);
// 保存用户
try {
userMapper.insert(user);
}catch (Exception e){
log.error("用户创建失败");
}
return user;
}
}

@ -20,6 +20,9 @@ spring:
socketFactory:
port: 465
class: javax.net.ssl.SSLSocketFactory
redis:
host: 127.0.0.1
port: 6379
knife4j:
enable: true
openapi:

@ -14,23 +14,7 @@
</resultMap>
<insert id="insert" parameterType="com.unilife.model.entity.User" useGeneratedKeys="true" keyProperty="id">
INSERT INTO users (
username,
email,
password,
nickname,
avatar,
bio,
gender,
student_id,
department,
major,
grade,
points,
role,
status,
is_verified,
login_ip,
login_time
username, email, password,nickname,avatar,bio, gender,student_id,department, major,grade,points,role,status,is_verified,login_ip,login_time
) VALUES (
#{username},
#{email},
@ -57,4 +41,25 @@
FROM users
WHERE email = #{email} AND password = #{password}
</select>
<select id="getUserByEmail" resultType="com.unilife.model.entity.User">
select username,
email,
password,
nickname,
avatar,
bio,
gender,
student_id,
department,
major,
grade,
points,
role,
status,
is_verified,
login_ip,
login_time
from users where email=#{email};
</select>
</mapper>
Loading…
Cancel
Save