修正映射重复问题,修改加密方式 #54

Merged
hnu202326010122 merged 1 commits from jingyou_branch into develop 1 month ago

@ -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;
/**
* MD5Spring SecurityPasswordEncoder
*/
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);
}
}

@ -54,11 +54,12 @@ public class SecurityConfig {
/**
*
*/
// com/campus/water/config/SecurityConfig.java
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
// 替换为MD5加密器
return new MD5PasswordEncoder();
}
/**
*
*/

@ -1,44 +0,0 @@
package com.campus.water.entity.po;
import lombok.Data;
import jakarta.persistence.*;
/**
* PO
* adminAdmin
*/
@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; // 默认为空,可在业务层设置默认值
}

@ -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; // 维修人员姓名
}

@ -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();
}

@ -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<RepairerAuthPO, Long> {
// 根据用户名查询认证信息(适配PO类)
Optional<RepairerAuthPO> findByUsername(String username);
public interface RepairerAuthRepository extends JpaRepository<RepairerAuth, Long> { // 实体类改为RepairerAuth
// 根据用户名查询认证信息(适配RepairerAuth类)
Optional<RepairerAuth> findByUsername(String username);
// 根据维修人员ID查询认证信息适配PO类)
Optional<RepairerAuthPO> findByRepairmanId(String repairmanId);
// 根据维修人员ID查询认证信息适配RepairerAuth类)
Optional<RepairerAuth> findByRepairmanId(String repairmanId);
// 根据账户状态查询认证信息(引用PO内的枚举)
List<RepairerAuthPO> findByAccountStatus(RepairerAuthPO.AccountStatus accountStatus);
// 根据账户状态查询认证信息(引用RepairerAuth内的枚举)
List<RepairerAuth> findByAccountStatus(RepairerAuth.AccountStatus accountStatus);
// 查找活跃状态的维修人员账号JPQL实体类名改为RepairerAuthPO
@Query("SELECT ra FROM RepairerAuthPO ra WHERE ra.username = ?1 AND ra.accountStatus = 'active'")
Optional<RepairerAuthPO> findActiveByUsername(String username);
// 查找活跃状态的维修人员账号JPQL实体类名改为RepairerAuth
@Query("SELECT ra FROM RepairerAuth ra WHERE ra.username = ?1 AND ra.accountStatus = 'active'")
Optional<RepairerAuth> findActiveByUsername(String username);
// 检查用户名是否存在
boolean existsByUsername(String username);

@ -1,6 +1,7 @@
package com.campus.water.mapper; // 核心修正从mapper改为repositoryJPA规范
// filePathmain/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<UserPO, String> {
// 根据学号查找用户适配PO类字段名保持studentId不变
Optional<UserPO> findByStudentId(String studentId);
public interface UserRepository extends JpaRepository<User, String> { // 泛型改为User
// 根据学号查找用户
Optional<User> findByStudentId(String studentId);
// 根据学生姓名模糊查询(适配PO的username字段原studentName对应PO的username
List<UserPO> findByUsernameContaining(String username);
// 根据学生姓名模糊查询(User中字段为studentName
List<User> findByStudentNameContaining(String studentName);
// 根据用户状态查询(引用PO内的UserStatus枚举
List<UserPO> findByStatus(UserPO.UserStatus status);
// 根据用户状态查询(引用User内的UserStatus枚举
List<User> findByStatus(User.UserStatus status);
// 根据手机号查询用户
Optional<UserPO> findByPhone(String phone);
Optional<User> findByPhone(String phone);
// 根据邮箱查询用户
Optional<UserPO> findByEmail(String email);
Optional<User> findByEmail(String email);
// 按姓名模糊查询和状态筛选(JPQL实体类名改为UserPOstudentName改为username
@Query("SELECT u FROM UserPO u WHERE u.username LIKE %?1% AND u.status = ?2")
List<UserPO> findByUsernameContainingAndStatus(String username, UserPO.UserStatus status);
// 按姓名模糊查询和状态筛选(调整实体类名和字段名
@Query("SELECT u FROM User u WHERE u.studentName LIKE %?1% AND u.status = ?2")
List<User> findByStudentNameContainingAndStatus(String studentName, User.UserStatus status);
// 检查学号是否已存在
boolean existsByStudentId(String studentId);
@ -38,9 +39,9 @@ public interface UserRepository extends JpaRepository<UserPO, String> {
// 检查邮箱是否已存在
boolean existsByEmail(String email);
// 检查用户名是否存在
boolean existsByUsername(String username);
// 检查用户名studentName是否存在(登录核心方法)
boolean existsByStudentName(String studentName);
// ========== 新增:登录核心方法(必须) ==========
Optional<UserPO> findByUsername(String username);
// 登录核心方法根据用户名studentName查询
Optional<User> findByStudentName(String studentName);
}

@ -1,14 +1,14 @@
// filePathmain/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))

@ -1,8 +1,9 @@
// filePathmain/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())) {

@ -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);
}

Loading…
Cancel
Save