hongjli
2025-04-15 1acf9a48021d0af1d81fdf3ed8fcf8dffd020f6b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
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);
    }