diff --git a/backend/pom.xml b/backend/pom.xml index 72dab6f0..d89a843c 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -167,6 +167,14 @@ guava 32.1.3-jre + + org.flywaydb + flyway-core + + + org.flywaydb + flyway-mysql + diff --git a/backend/src/main/java/com/qqchen/deploy/backend/framework/enums/ResponseCode.java b/backend/src/main/java/com/qqchen/deploy/backend/framework/enums/ResponseCode.java index 7a8bc5eb..dd0c1a06 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/framework/enums/ResponseCode.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/framework/enums/ResponseCode.java @@ -13,20 +13,11 @@ public enum ResponseCode { NOT_FOUND(404, "response.not.found"), CONFLICT(409, "response.conflict"), - // 业务错误码 - TENANT_NOT_FOUND(1001, "tenant.not.found"), - DATA_NOT_FOUND(1002, "data.not.found"), - // 系统异常 (1开头) - OPTIMISTIC_LOCK_ERROR(1003, "system.optimistic.lock.error"), // 乐观锁异常 - PESSIMISTIC_LOCK_ERROR(1004, "system.pessimistic.lock.error"), // 悲观锁异常 - CONCURRENT_UPDATE_ERROR(1005, "system.concurrent.update.error"), // 并发更新异常 - RETRY_EXCEEDED_ERROR(1006, "system.retry.exceeded.error"), // 重试次数超限异常 - - // 用户相关错误码(2开头) - USER_NOT_FOUND(2001, "user.not.found"), - USERNAME_EXISTS(2002, "user.username.exists"), - EMAIL_EXISTS(2003, "user.email.exists"), + OPTIMISTIC_LOCK_ERROR(1001, "system.optimistic.lock.error"), // 乐观锁异常 + PESSIMISTIC_LOCK_ERROR(1002, "system.pessimistic.lock.error"), // 悲观锁异常 + CONCURRENT_UPDATE_ERROR(1003, "system.concurrent.update.error"), // 并发更新异常 + RETRY_EXCEEDED_ERROR(1004, "system.retry.exceeded.error"), // 重试次数超限异常 // 依赖注入相关错误 (1100-1199) DEPENDENCY_INJECTION_SERVICE_NOT_FOUND(1100, "dependency.injection.service.not.found"), @@ -34,13 +25,20 @@ public enum ResponseCode { DEPENDENCY_INJECTION_CONVERTER_NOT_FOUND(1102, "dependency.injection.converter.not.found"), DEPENDENCY_INJECTION_ENTITYPATH_FAILED(1103, "dependency.injection.entitypath.failed"), + // 业务异常 (2开头) + TENANT_NOT_FOUND(2001, "tenant.not.found"), + DATA_NOT_FOUND(2002, "data.not.found"), + USER_NOT_FOUND(2003, "user.not.found"), + USERNAME_EXISTS(2004, "user.username.exists"), + EMAIL_EXISTS(2005, "user.email.exists"), + LOGIN_ERROR(2006, "user.login.error"), + // JWT相关错误码 (2100-2199) JWT_EXPIRED(2100, "jwt.token.expired"), JWT_INVALID(2101, "jwt.token.invalid"), JWT_MISSING(2102, "jwt.token.missing"); private final int code; - private final String messageKey; // 国际化消息key ResponseCode(int code, String messageKey) { diff --git a/backend/src/main/java/com/qqchen/deploy/backend/framework/exception/GlobalExceptionHandler.java b/backend/src/main/java/com/qqchen/deploy/backend/framework/exception/GlobalExceptionHandler.java index 64943cdd..c884e09e 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/framework/exception/GlobalExceptionHandler.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/framework/exception/GlobalExceptionHandler.java @@ -22,12 +22,8 @@ public class GlobalExceptionHandler { @ExceptionHandler(BusinessException.class) public Response handleBusinessException(BusinessException e) { - String message = messageSource.getMessage( - e.getErrorCode().getMessageKey(), - e.getArgs(), - LocaleContextHolder.getLocale() - ); - return Response.error(e.getErrorCode(), message); + log.warn("Business error occurred: {}", e.getErrorCode().getMessageKey(), e); + return Response.error(e.getErrorCode()); } @ExceptionHandler(SystemException.class) @@ -36,6 +32,12 @@ public class GlobalExceptionHandler { return Response.error(ResponseCode.ERROR); } + @ExceptionHandler(org.springframework.security.authentication.BadCredentialsException.class) + public Response handleBadCredentialsException(org.springframework.security.authentication.BadCredentialsException e) { + log.warn("Login failed: Bad credentials", e); + return Response.error(ResponseCode.LOGIN_ERROR); + } + @ExceptionHandler(Exception.class) public Response handleException(Exception e) { log.error("Unexpected error occurred", e); diff --git a/backend/src/main/java/com/qqchen/deploy/backend/service/impl/UserServiceImpl.java b/backend/src/main/java/com/qqchen/deploy/backend/service/impl/UserServiceImpl.java index cf1c0ff2..2fb939c8 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/service/impl/UserServiceImpl.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/service/impl/UserServiceImpl.java @@ -41,6 +41,9 @@ public class UserServiceImpl extends BaseServiceImpl implem @Resource private AuthenticationManager authenticationManager; + + @Resource + private IUserRepository userRepository; @Resource private JwtTokenUtil jwtTokenUtil; @@ -78,27 +81,22 @@ public class UserServiceImpl extends BaseServiceImpl implem @Transactional(readOnly = true) @Audited(action = "USER_LOGIN", detail = "登录") public LoginResponse login(LoginRequest request) { -// Authentication authentication = authenticationManager.authenticate( -// new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword()) -// ); -// -// UserDetails userDetails = (UserDetails) authentication.getPrincipal(); -// String token = jwtTokenUtil.generateToken(userDetails); -// -// User user = userRepository.findByUsernameAndDeletedFalse(userDetails.getUsername()) -// .orElseThrow(() -> new BusinessException(ResponseCode.USER_NOT_FOUND)); -// -// LoginResponse response = new LoginResponse(); -// response.setId(user.getId()); -// response.setUsername(user.getUsername()); -// response.setNickname(user.getNickname()); -// response.setEmail(user.getEmail()); -// response.setPhone(user.getPhone()); -// response.setToken(token); -// -// log.info("用户 {} ({}) 登录成功", user.getUsername(), user.getNickname()); -// return response; - return null; + Authentication authentication = authenticationManager.authenticate( + new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword()) + ); + UserDetails userDetails = (UserDetails) authentication.getPrincipal(); + String token = jwtTokenUtil.generateToken(userDetails); + User user = userRepository.findByUsernameAndDeletedFalse(userDetails.getUsername()) + .orElseThrow(() -> new BusinessException(ResponseCode.USER_NOT_FOUND)); + LoginResponse response = new LoginResponse(); + response.setId(user.getId()); + response.setUsername(user.getUsername()); + response.setNickname(user.getNickname()); + response.setEmail(user.getEmail()); + response.setPhone(user.getPhone()); + response.setToken(token); + log.info("用户 {} ({}) 登录成功", user.getUsername(), user.getNickname()); + return response; } @Override diff --git a/backend/src/main/resources/db/migration/V1.0.0__init_schema.sql b/backend/src/main/resources/db/migration/V1.0.0__init_schema.sql new file mode 100644 index 00000000..b42c9416 --- /dev/null +++ b/backend/src/main/resources/db/migration/V1.0.0__init_schema.sql @@ -0,0 +1,36 @@ +-- 创建租户表 +CREATE TABLE IF NOT EXISTS sys_tenant ( + id BIGINT AUTO_INCREMENT PRIMARY KEY, + create_by VARCHAR(255) NULL, + create_time DATETIME(6) NULL, + deleted BIT NOT NULL DEFAULT 0, + update_by VARCHAR(255) NULL, + update_time DATETIME(6) NULL, + version INT NOT NULL DEFAULT 0, + address VARCHAR(255) NULL, + code VARCHAR(255) NOT NULL, + contact_name VARCHAR(255) NULL, + contact_phone VARCHAR(255) NULL, + email VARCHAR(255) NULL, + enabled BIT NOT NULL DEFAULT 1, + name VARCHAR(255) NOT NULL, + CONSTRAINT UK_tenant_code UNIQUE (code) +); + +-- 创建用户表 +CREATE TABLE IF NOT EXISTS sys_user ( + id BIGINT AUTO_INCREMENT PRIMARY KEY, + create_by VARCHAR(255) NULL, + create_time DATETIME(6) NULL, + deleted BIT NOT NULL DEFAULT 0, + update_by VARCHAR(255) NULL, + update_time DATETIME(6) NULL, + version INT NOT NULL DEFAULT 0, + email VARCHAR(255) NULL, + enabled BIT NOT NULL DEFAULT 1, + nickname VARCHAR(50) NULL, + password VARCHAR(255) NOT NULL, + phone VARCHAR(255) NULL, + username VARCHAR(255) NOT NULL, + CONSTRAINT UK_user_username UNIQUE (username) +); \ No newline at end of file diff --git a/backend/src/main/resources/db/migration/V1.0.1__init_data.sql b/backend/src/main/resources/db/migration/V1.0.1__init_data.sql new file mode 100644 index 00000000..d8aac844 --- /dev/null +++ b/backend/src/main/resources/db/migration/V1.0.1__init_data.sql @@ -0,0 +1,17 @@ +-- 插入初始租户 +INSERT INTO sys_tenant +(create_by, create_time, deleted, update_by, update_time, version, +address, code, contact_name, contact_phone, email, enabled, name) +VALUES +('system', NOW(), 0, 'system', NOW(), 0, +'北京市朝阳区xxx街道', 'default', '张三', '13900000001', 'default@example.com', 1, '默认租户'); + +-- 插入管理员用户 +INSERT INTO sys_user +(create_by, create_time, deleted, update_by, update_time, version, +email, enabled, nickname, password, phone, username) +VALUES +('system', NOW(), 0, 'system', NOW(), 0, +'admin@example.com', 1, '系统管理员', +'$2a$10$mW/yJPHjyueQ1g82qWXg8eYqyUVNxFQPagkUvqtWPhKhqB8Z3Vw2y', +'13800138000', 'admin'); \ No newline at end of file diff --git a/backend/src/main/resources/messages.properties b/backend/src/main/resources/messages.properties index 80956c58..365cde69 100644 --- a/backend/src/main/resources/messages.properties +++ b/backend/src/main/resources/messages.properties @@ -16,6 +16,7 @@ data.not.found=找不到ID为{0}的{1} user.not.found=用户不存在 user.username.exists=用户名已存在 user.email.exists=邮箱已存在 +user.login.error=用户名或密码错误 # 系统异常消息 system.optimistic.lock.error=数据已被其他用户修改,请刷新后重试 diff --git a/backend/src/main/resources/messages_en.properties b/backend/src/main/resources/messages_en.properties index 9a89855a..85e35d25 100644 --- a/backend/src/main/resources/messages_en.properties +++ b/backend/src/main/resources/messages_en.properties @@ -16,6 +16,7 @@ data.not.found={0} with id {1} not found user.not.found=User not found user.username.exists=Username already exists user.email.exists=Email already exists +user.login.error=Invalid username or password # System Exception Messages system.optimistic.lock.error=Data has been modified by another user, please refresh and try again diff --git a/backend/src/main/resources/messages_zh_CN.properties b/backend/src/main/resources/messages_zh_CN.properties index 3cd273b7..76d59054 100644 --- a/backend/src/main/resources/messages_zh_CN.properties +++ b/backend/src/main/resources/messages_zh_CN.properties @@ -16,6 +16,7 @@ data.not.found=数据不存在 user.not.found=用户不存在 user.username.exists=用户名已存在 user.email.exists=邮箱已存在 +user.login.error=用户名或密码错误 # 系统异常消息 system.optimistic.lock.error=数据已被其他用户修改,请刷新后重试