package com.weiwojc.service.impl;
|
|
import com.weiwojc.mapper.UserMapper;
|
import com.weiwojc.model.dto.UserLoginDTO;
|
import com.weiwojc.model.dto.UserRegisterDTO;
|
import com.weiwojc.model.entity.User;
|
import com.weiwojc.service.UserService;
|
import com.weiwojc.utils.JwtUtils;
|
import com.weiwojc.utils.PasswordUtils;
|
import lombok.RequiredArgsConstructor;
|
import org.springframework.security.authentication.BadCredentialsException;
|
import org.springframework.security.authentication.LockedException;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
|
import java.time.LocalDateTime;
|
import java.util.UUID;
|
|
@Service
|
@RequiredArgsConstructor
|
public class UserServiceImpl implements UserService {
|
|
private final UserMapper userMapper;
|
private final JwtUtils jwtUtils;
|
|
@Override
|
@Transactional
|
public User register(UserRegisterDTO registerDTO) {
|
// 检查账号名是否已存在
|
User existingUser = userMapper.findByUsername(registerDTO.getAccountName());
|
if (existingUser != null) {
|
throw new RuntimeException("账号名已存在");
|
}
|
|
// 创建新用户
|
User user = new User();
|
user.setUuid(UUID.randomUUID().toString());
|
user.setUsername(registerDTO.getAccountName());
|
user.setNickname(registerDTO.getNickname());
|
|
// 生成加密密码
|
String salt = PasswordUtils.generateSalt();
|
String hashedPassword = PasswordUtils.hashPassword(registerDTO.getPassword(), salt);
|
user.setPasswordHash(hashedPassword);
|
user.setPasswordSalt(salt); // 保存盐值
|
|
// 设置其他字段
|
user.setStatus(1); // 正常状态
|
user.setRegisteredAt(LocalDateTime.now());
|
user.setUpdatedAt(LocalDateTime.now());
|
|
// 保存用户
|
userMapper.insert(user);
|
return user;
|
}
|
|
@Override
|
public String login(UserLoginDTO loginDTO) {
|
User user = userMapper.findByUsername(loginDTO.getAccountName());
|
|
if (user == null) {
|
throw new BadCredentialsException("账号名或密码错误");
|
}
|
|
// 检查账户状态
|
if (user.getStatus() == 0) {
|
throw new LockedException("账户已被禁用");
|
}
|
|
// 检查是否被锁定
|
if (isUserLocked(user.getUserId())) {
|
throw new LockedException("账户已被锁定,请稍后再试");
|
}
|
|
// 验证密码
|
if (!PasswordUtils.verifyPassword(loginDTO.getPassword(), user.getPasswordHash())) {
|
// 增加登录失败次数
|
incrementLoginAttempts(user.getUsername());
|
throw new BadCredentialsException("账号名或密码错误");
|
}
|
|
// 重置登录失败次数
|
resetLoginAttempts(user.getUsername());
|
|
// 更新最后登录时间
|
updateLastLogin(user.getUserId());
|
|
// 生成JWT令牌
|
return jwtUtils.generateToken(user);
|
}
|
|
@Override
|
public User getUserInfo(Long userId) {
|
return userMapper.findById(userId);
|
}
|
|
@Override
|
public void updateLastLogin(Long userId) {
|
userMapper.updateLastLogin(userId, LocalDateTime.now());
|
}
|
|
@Override
|
public boolean isUserLocked(Long userId) {
|
User user = userMapper.findById(userId);
|
if (user == null) {
|
return false;
|
}
|
|
// 检查账户锁定状态
|
if (user.getLockedUntil() != null &&
|
LocalDateTime.now().isBefore(user.getLockedUntil())) {
|
return true;
|
}
|
|
return false;
|
}
|
|
@Override
|
public void incrementLoginAttempts(String username) {
|
User user = userMapper.findByUsername(username);
|
|
if (user != null) {
|
int attempts = user.getLoginAttempts() == null ? 0 : user.getLoginAttempts();
|
attempts++;
|
|
LocalDateTime lockedUntil = null;
|
// 如果失败次数达到5次,锁定30分钟
|
if (attempts >= 5) {
|
lockedUntil = LocalDateTime.now().plusMinutes(30);
|
}
|
|
userMapper.updateLoginAttempts(user.getUserId(), attempts, lockedUntil);
|
}
|
}
|
|
@Override
|
public void resetLoginAttempts(String username) {
|
userMapper.resetLoginAttempts(username);
|
}
|
}
|