From e9268506bbc9633b220852708598f1bd39f26e48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E7=AB=9E=E7=94=B1?= <1193626695@qq.com> Date: Mon, 8 Dec 2025 11:01:30 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E6=98=A0=E5=B0=84=E9=87=8D?= =?UTF-8?q?=E5=A4=8D=E9=97=AE=E9=A2=98=EF=BC=8C=E4=BF=AE=E6=94=B9=E5=8A=A0?= =?UTF-8?q?=E5=AF=86=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../water/config/MD5PasswordEncoder.java | 26 ++++++++++ .../campus/water/config/SecurityConfig.java | 5 +- .../com/campus/water/entity/po/AdminPO.java | 44 ---------------- .../water/entity/po/RepairerAuthPO.java | 37 -------------- .../com/campus/water/entity/po/UserPO.java | 48 ----------------- .../water/mapper/RepairerAuthRepository.java | 22 ++++---- .../campus/water/mapper/UserRepository.java | 37 +++++++------- .../security/UserDetailsServiceImpl.java | 51 +++++++------------ .../campus/water/service/LoginService.java | 17 ++++--- .../campus/water/service/RegisterService.java | 30 ++++++----- 10 files changed, 102 insertions(+), 215 deletions(-) create mode 100644 src/main/java/com/campus/water/config/MD5PasswordEncoder.java delete mode 100644 src/main/java/com/campus/water/entity/po/AdminPO.java delete mode 100644 src/main/java/com/campus/water/entity/po/RepairerAuthPO.java delete mode 100644 src/main/java/com/campus/water/entity/po/UserPO.java diff --git a/src/main/java/com/campus/water/config/MD5PasswordEncoder.java b/src/main/java/com/campus/water/config/MD5PasswordEncoder.java new file mode 100644 index 0000000..061d491 --- /dev/null +++ b/src/main/java/com/campus/water/config/MD5PasswordEncoder.java @@ -0,0 +1,26 @@ +// com/campus/water/config/MD5PasswordEncoder.java +package com.campus.water.config; + +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.util.DigestUtils; + +import java.nio.charset.StandardCharsets; + +/** + * 自定义MD5密码编码器,实现Spring Security的PasswordEncoder接口 + */ +public class MD5PasswordEncoder implements PasswordEncoder { + + @Override + public String encode(CharSequence rawPassword) { + // 对原始密码进行MD5加密(与注册时的加密方式保持一致) + return DigestUtils.md5DigestAsHex(rawPassword.toString().getBytes(StandardCharsets.UTF_8)); + } + + @Override + public boolean matches(CharSequence rawPassword, String encodedPassword) { + // 验证时:将原始密码MD5加密后与数据库中存储的加密密码对比 + String rawEncoded = encode(rawPassword); + return rawEncoded.equals(encodedPassword); + } +} \ No newline at end of file diff --git a/src/main/java/com/campus/water/config/SecurityConfig.java b/src/main/java/com/campus/water/config/SecurityConfig.java index f2534fe..55c06fa 100644 --- a/src/main/java/com/campus/water/config/SecurityConfig.java +++ b/src/main/java/com/campus/water/config/SecurityConfig.java @@ -54,11 +54,12 @@ public class SecurityConfig { /** * 密码加密器 */ + // com/campus/water/config/SecurityConfig.java @Bean public PasswordEncoder passwordEncoder() { - return new BCryptPasswordEncoder(); + // 替换为MD5加密器 + return new MD5PasswordEncoder(); } - /** * 认证管理器 */ diff --git a/src/main/java/com/campus/water/entity/po/AdminPO.java b/src/main/java/com/campus/water/entity/po/AdminPO.java deleted file mode 100644 index dacdb70..0000000 --- a/src/main/java/com/campus/water/entity/po/AdminPO.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.campus.water.entity.po; - -import lombok.Data; -import jakarta.persistence.*; - -/** - * 管理员PO类(数据库映射对象) - * 对应数据库admin表,已与Admin实体类统一映射规则 - */ -@Data -@Entity -@Table(name = "admin") // 对应数据库admin表 -public class AdminPO { - @Id - @Column(name = "admin_id", length = 50) // 明确映射数据库列admin_id,与Admin类保持一致 - private String adminId; // 移除自增注解,因String类型不支持IDENTITY自增 - - @Column(name = "admin_name", length = 50, unique = true, nullable = false) - private String username; // 统一映射到数据库列admin_name,与Admin类的adminName保持一致 - - @Column(name = "password", length = 200, nullable = false) - private String password; // MD5加密后的密码,与Admin类字段长度保持一致 - - @Column(name = "phone", length = 20) - private String phone; // 联系电话,统一长度约束 - - // 管理员角色枚举(与Admin类的AdminRole取值和大小写保持一致) - public enum AdminRole { - super_admin, area_admin, viewer - } - - // 管理员状态枚举(与Admin类的AdminStatus取值和大小写保持一致) - public enum AdminStatus { - active, inactive - } - - @Enumerated(EnumType.STRING) - @Column(name = "role", length = 50, nullable = false) - private AdminRole role; // 默认为空,可在业务层设置默认值 - - @Enumerated(EnumType.STRING) - @Column(name = "status", length = 50, nullable = false) - private AdminStatus status; // 默认为空,可在业务层设置默认值 -} \ No newline at end of file diff --git a/src/main/java/com/campus/water/entity/po/RepairerAuthPO.java b/src/main/java/com/campus/water/entity/po/RepairerAuthPO.java deleted file mode 100644 index 9eb2acd..0000000 --- a/src/main/java/com/campus/water/entity/po/RepairerAuthPO.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.campus.water.entity.po; - -import lombok.Data; -import jakarta.persistence.*; - -@Data -@Entity -@Table(name = "repairer_auth_backup") // 对应数据库表 -public class RepairerAuthPO { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) // 主键自增(Long类型) - private Long id; // 主键ID(对应Repository的Long主键类型) - - @Column(unique = true, nullable = false) - private String repairmanId; // 维修人员唯一标识(业务ID) - - @Column(unique = true, nullable = false) - private String username; // 登录用户名 - - @Column(nullable = false) - private String password; // MD5加密密码 - - // 账号状态枚举(解决字段映射冲突) - public enum AccountStatus { - active, inactive, locked - } - - // 明确指定数据库字段名,与实体类字段形成映射,解决冲突 - @Enumerated(EnumType.STRING) - @Column(name = "account_status", length = 50, nullable = false) - private AccountStatus accountStatus; - - // 补充其他业务字段 - private String phone; // 联系电话 - private String areaId; // 负责区域ID - private String name; // 维修人员姓名 -} \ No newline at end of file diff --git a/src/main/java/com/campus/water/entity/po/UserPO.java b/src/main/java/com/campus/water/entity/po/UserPO.java deleted file mode 100644 index 1d29998..0000000 --- a/src/main/java/com/campus/water/entity/po/UserPO.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.campus.water.entity.po; - -import lombok.Data; -import jakarta.persistence.*; -import java.time.LocalDateTime; - -@Data -@Entity -@Table(name = "user") // 对应数据库user表(学生用户) -public class UserPO { - @Id - @Column(name = "student_id", length = 50) // 与User类保持字段名一致 - private String studentId; // 学生ID(主键,学号) - - @Column(name = "student_name", unique = true, nullable = false, length = 50) - // 修正:与User类的studentName字段对应,同时保留唯一约束 - private String username; // 登录名(对应User类的studentName) - - @Column(name = "password", nullable = false, length = 200) - private String password; // MD5加密后的密码(与User类字段长度保持一致) - - @Column(name = "phone", length = 20) - private String phone; // 联系电话 - - // 移除冗余的studentNo字段(与studentId重复) - private String college; // 学院 - - @Column(name = "email", unique = true, length = 100) - private String email; // 邮箱(与User类字段长度保持一致) - - // 统一状态枚举命名风格与User类保持一致(小写开头) - public enum UserStatus { - active, // 活跃 - inactive, // 未激活 - locked // 锁定 - } - - @Enumerated(EnumType.STRING) - @Column(name = "status", length = 50) - private UserStatus status = UserStatus.active; // 增加默认值,与User类保持一致 - - // 补充时间字段,与User类保持表结构一致 - @Column(name = "create_time") - private LocalDateTime createTime = LocalDateTime.now(); - - @Column(name = "updated_time") - private LocalDateTime updatedTime = LocalDateTime.now(); -} \ No newline at end of file diff --git a/src/main/java/com/campus/water/mapper/RepairerAuthRepository.java b/src/main/java/com/campus/water/mapper/RepairerAuthRepository.java index 1885d35..a0b97e1 100644 --- a/src/main/java/com/campus/water/mapper/RepairerAuthRepository.java +++ b/src/main/java/com/campus/water/mapper/RepairerAuthRepository.java @@ -1,6 +1,6 @@ package com.campus.water.mapper; -import com.campus.water.entity.po.RepairerAuthPO; // 替换为PO包下的实体类 +import com.campus.water.entity.RepairerAuth; // 改为entity包下的RepairerAuth import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; @@ -9,19 +9,19 @@ import java.util.List; import java.util.Optional; @Repository -public interface RepairerAuthRepository extends JpaRepository { - // 根据用户名查询认证信息(适配PO类) - Optional findByUsername(String username); +public interface RepairerAuthRepository extends JpaRepository { // 实体类改为RepairerAuth + // 根据用户名查询认证信息(适配RepairerAuth类) + Optional findByUsername(String username); - // 根据维修人员ID查询认证信息(适配PO类) - Optional findByRepairmanId(String repairmanId); + // 根据维修人员ID查询认证信息(适配RepairerAuth类) + Optional findByRepairmanId(String repairmanId); - // 根据账户状态查询认证信息(引用PO内的枚举) - List findByAccountStatus(RepairerAuthPO.AccountStatus accountStatus); + // 根据账户状态查询认证信息(引用RepairerAuth内的枚举) + List findByAccountStatus(RepairerAuth.AccountStatus accountStatus); - // 查找活跃状态的维修人员账号(JPQL实体类名改为RepairerAuthPO) - @Query("SELECT ra FROM RepairerAuthPO ra WHERE ra.username = ?1 AND ra.accountStatus = 'active'") - Optional findActiveByUsername(String username); + // 查找活跃状态的维修人员账号(JPQL实体类名改为RepairerAuth) + @Query("SELECT ra FROM RepairerAuth ra WHERE ra.username = ?1 AND ra.accountStatus = 'active'") + Optional findActiveByUsername(String username); // 检查用户名是否存在 boolean existsByUsername(String username); diff --git a/src/main/java/com/campus/water/mapper/UserRepository.java b/src/main/java/com/campus/water/mapper/UserRepository.java index 9613c5a..85bcf39 100644 --- a/src/main/java/com/campus/water/mapper/UserRepository.java +++ b/src/main/java/com/campus/water/mapper/UserRepository.java @@ -1,6 +1,7 @@ -package com.campus.water.mapper; // 核心修正:从mapper改为repository(JPA规范) +// filePath:main/java/com/campus/water/mapper/UserRepository.java +package com.campus.water.mapper; -import com.campus.water.entity.po.UserPO; // 替换为PO包下的实体类 +import com.campus.water.entity.User; // 改为引用User实体类 import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; @@ -9,25 +10,25 @@ import java.util.List; import java.util.Optional; @Repository -public interface UserRepository extends JpaRepository { - // 根据学号查找用户(适配PO类,字段名保持studentId不变) - Optional findByStudentId(String studentId); +public interface UserRepository extends JpaRepository { // 泛型改为User + // 根据学号查找用户 + Optional findByStudentId(String studentId); - // 根据学生姓名模糊查询(适配PO的username字段,原studentName对应PO的username) - List findByUsernameContaining(String username); + // 根据学生姓名模糊查询(User中字段为studentName) + List findByStudentNameContaining(String studentName); - // 根据用户状态查询(引用PO内的UserStatus枚举) - List findByStatus(UserPO.UserStatus status); + // 根据用户状态查询(引用User内的UserStatus枚举) + List findByStatus(User.UserStatus status); // 根据手机号查询用户 - Optional findByPhone(String phone); + Optional findByPhone(String phone); // 根据邮箱查询用户 - Optional findByEmail(String email); + Optional findByEmail(String email); - // 按姓名模糊查询和状态筛选(JPQL实体类名改为UserPO,studentName改为username) - @Query("SELECT u FROM UserPO u WHERE u.username LIKE %?1% AND u.status = ?2") - List findByUsernameContainingAndStatus(String username, UserPO.UserStatus status); + // 按姓名模糊查询和状态筛选(调整实体类名和字段名) + @Query("SELECT u FROM User u WHERE u.studentName LIKE %?1% AND u.status = ?2") + List findByStudentNameContainingAndStatus(String studentName, User.UserStatus status); // 检查学号是否已存在 boolean existsByStudentId(String studentId); @@ -38,9 +39,9 @@ public interface UserRepository extends JpaRepository { // 检查邮箱是否已存在 boolean existsByEmail(String email); - // 检查用户名是否存在 - boolean existsByUsername(String username); + // 检查用户名(studentName)是否存在(登录核心方法) + boolean existsByStudentName(String studentName); - // ========== 新增:登录核心方法(必须) ========== - Optional findByUsername(String username); + // 登录核心方法:根据用户名(studentName)查询 + Optional findByStudentName(String studentName); } \ No newline at end of file diff --git a/src/main/java/com/campus/water/security/UserDetailsServiceImpl.java b/src/main/java/com/campus/water/security/UserDetailsServiceImpl.java index 1df2fba..0f45394 100644 --- a/src/main/java/com/campus/water/security/UserDetailsServiceImpl.java +++ b/src/main/java/com/campus/water/security/UserDetailsServiceImpl.java @@ -1,14 +1,14 @@ +// filePath:main/java/com/campus/water/security/UserDetailsServiceImpl.java package com.campus.water.security; -import com.campus.water.entity.Admin; // 改为引用Admin实体下的Admin实体类 -import com.campus.water.entity.po.RepairerAuthPO; -import com.campus.water.entity.po.UserPO; +import com.campus.water.entity.Admin; +import com.campus.water.entity.RepairerAuth; +import com.campus.water.entity.User; // 自定义User实体类(保留) import com.campus.water.mapper.AdminRepository; import com.campus.water.mapper.RepairerAuthRepository; import com.campus.water.mapper.UserRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; @@ -16,60 +16,43 @@ import org.springframework.stereotype.Service; import java.util.Collections; -/** - * 加载用户权限信息 - */ @Service public class UserDetailsServiceImpl implements UserDetailsService { @Autowired - private UserRepository userRepository; // 学生用户仓库 + private UserRepository userRepository; @Autowired - private AdminRepository adminRepository; // 管理员仓库 + private AdminRepository adminRepository; @Autowired - private RepairerAuthRepository repairerAuthRepository; // 维修人员仓库 + private RepairerAuthRepository repairerAuthRepository; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { - // 1. 尝试查询学生用户 - UserPO student = userRepository.findByUsername(username).orElse(null); + // 1. 查询自定义User实体(学生用户) + User student = userRepository.findByStudentName(username).orElse(null); if (student != null) { - return createUserDetails( - student.getUsername(), - student.getPassword(), - RoleConstants.ROLE_STUDENT - ); + return createUserDetails(student.getStudentName(), student.getPassword(), RoleConstants.ROLE_STUDENT); } - // 2. 尝试查询管理员用户(适配Admin实体类的adminName字段) - Admin admin = adminRepository.findByAdminName(username).orElse(null); // 方法名从findByUsername改为findByAdminName + // 2. 查询管理员用户 + Admin admin = adminRepository.findByAdminName(username).orElse(null); if (admin != null) { - return createUserDetails( - admin.getAdminName(), // 字段名从getUsername改为getAdminName - admin.getPassword(), - RoleConstants.ROLE_ADMIN - ); + return createUserDetails(admin.getAdminName(), admin.getPassword(), RoleConstants.ROLE_ADMIN); } - // 3. 尝试查询维修人员用户 - RepairerAuthPO repairer = repairerAuthRepository.findByUsername(username).orElse(null); + // 3. 查询维修人员用户 + RepairerAuth repairer = repairerAuthRepository.findByUsername(username).orElse(null); if (repairer != null) { - return createUserDetails( - repairer.getUsername(), - repairer.getPassword(), - RoleConstants.ROLE_REPAIRMAN - ); + return createUserDetails(repairer.getUsername(), repairer.getPassword(), RoleConstants.ROLE_REPAIRMAN); } - // 所有类型用户都不存在 throw new UsernameNotFoundException("用户不存在: " + username); } - // 构建UserDetails对象的工具方法 private UserDetails createUserDetails(String username, String password, String role) { - return new User( + return new org.springframework.security.core.userdetails.User( username, password, Collections.singletonList(new SimpleGrantedAuthority(role)) diff --git a/src/main/java/com/campus/water/service/LoginService.java b/src/main/java/com/campus/water/service/LoginService.java index cae1572..c44d31e 100644 --- a/src/main/java/com/campus/water/service/LoginService.java +++ b/src/main/java/com/campus/water/service/LoginService.java @@ -1,8 +1,9 @@ +// filePath:main/java/com/campus/water/service/LoginService.java package com.campus.water.service; import com.campus.water.entity.Admin; -import com.campus.water.entity.po.RepairerAuthPO; -import com.campus.water.entity.po.UserPO; +import com.campus.water.entity.RepairerAuth; +import com.campus.water.entity.User; // 引入User实体类 import com.campus.water.entity.vo.LoginVO; import com.campus.water.mapper.AdminRepository; import com.campus.water.mapper.RepairerAuthRepository; @@ -15,10 +16,9 @@ import org.springframework.stereotype.Service; import java.util.UUID; @Service -@RequiredArgsConstructor // 自动生成构造函数(需要Lombok依赖) +@RequiredArgsConstructor public class LoginService { - // 依赖注入:通过构造函数初始化(@RequiredArgsConstructor自动生成构造函数) private final AdminRepository adminRepository; private final UserRepository userRepository; private final RepairerAuthRepository repairerAuthRepository; @@ -29,7 +29,6 @@ public class LoginService { String password = loginRequest.getPassword(); String userType = loginRequest.getUserType(); - // 增强版switch(解决"Switch语句可替换为增强的switch"警告) return switch (userType) { case "admin" -> handleAdminLogin(username, password); case "user" -> handleUserLogin(username, password); @@ -50,18 +49,22 @@ public class LoginService { } private LoginVO handleUserLogin(String username, String password) { - UserPO user = userRepository.findByUsername(username) + // 改为查询User实体,使用studentName字段匹配用户名 + User user = userRepository.findByStudentName(username) .orElseThrow(() -> new RuntimeException("用户不存在")); + // 验证密码(User的password字段与UserPO一致) if (!passwordEncoder.matches(password, user.getPassword())) { throw new RuntimeException("密码错误"); } + // 使用User的studentId作为用户ID return createLoginVO(user.getStudentId(), username, "user"); } private LoginVO handleRepairerLogin(String username, String password) { - RepairerAuthPO repairer = repairerAuthRepository.findByUsername(username) + // 此处将RepairerAuthPO改为RepairerAuth + RepairerAuth repairer = repairerAuthRepository.findByUsername(username) .orElseThrow(() -> new RuntimeException("维修人员不存在")); if (!passwordEncoder.matches(password, repairer.getPassword())) { diff --git a/src/main/java/com/campus/water/service/RegisterService.java b/src/main/java/com/campus/water/service/RegisterService.java index 538f474..61abe87 100644 --- a/src/main/java/com/campus/water/service/RegisterService.java +++ b/src/main/java/com/campus/water/service/RegisterService.java @@ -1,9 +1,9 @@ package com.campus.water.service; -import com.campus.water.entity.Admin; // 替换旧的AdminPO +import com.campus.water.entity.Admin; +import com.campus.water.entity.RepairerAuth; // 改为entity包下的RepairerAuth +import com.campus.water.entity.User; import com.campus.water.entity.dto.request.RegisterRequest; -import com.campus.water.entity.po.RepairerAuthPO; -import com.campus.water.entity.po.UserPO; import com.campus.water.mapper.AdminRepository; import com.campus.water.mapper.RepairerAuthRepository; import com.campus.water.mapper.UserRepository; @@ -27,6 +27,7 @@ public class RegisterService { public boolean register(RegisterRequest request) { String username = request.getUsername(); + // 使用与MD5PasswordEncoder相同的加密逻辑(UTF-8编码) String encryptedPwd = DigestUtils.md5DigestAsHex( request.getPassword().getBytes(StandardCharsets.UTF_8) ); @@ -67,22 +68,23 @@ public class RegisterService { } // 学生注册逻辑保持不变 - private void handleUserRegister(String username, String password, RegisterRequest request) { - if (userRepository.existsByUsername(username)) { + private void handleUserRegister(String studentName, String password, RegisterRequest request) { + // 检查用户名和学号是否已存在(保持不变) + if (userRepository.existsByStudentName(studentName)) { throw new RuntimeException("用户名已存在"); } if (userRepository.existsByStudentId(request.getStudentId())) { throw new RuntimeException("学号已被注册"); } - UserPO user = new UserPO(); - user.setUsername(username); - user.setPassword(password); - user.setStudentId(request.getStudentId()); - user.setUsername(request.getStudentName()); // 注意:这里重复设置了username,建议修正为setStudentName(如果有该字段) - // 枚举值改为小写(与UserPO中定义的一致) - user.setStatus(UserPO.UserStatus.active); + // 创建 User 实体对象(而非 UserPO) + User user = new User(); + user.setPassword(password); // 设置密码 + user.setStudentId(request.getStudentId()); // 设置学号 + user.setStudentName(request.getStudentName()); // 设置学生姓名 + user.setStatus(User.UserStatus.active); // 设置状态(使用 User 类的枚举) + // 保存 User 实体(与 UserRepository 类型匹配) userRepository.save(user); } @@ -95,11 +97,11 @@ public class RegisterService { throw new RuntimeException("维修人员ID已被注册"); } - RepairerAuthPO repairer = new RepairerAuthPO(); + RepairerAuth repairer = new RepairerAuth(); repairer.setUsername(username); repairer.setPassword(password); repairer.setRepairmanId(request.getRepairmanId()); - repairer.setAccountStatus(RepairerAuthPO.AccountStatus.active); + repairer.setAccountStatus(RepairerAuth.AccountStatus.active); repairerAuthRepository.save(repairer); } -- 2.34.1