diff --git a/src/main/java/asia/yulinling/workflow/config/CorsConfig.java b/src/main/java/asia/yulinling/workflow/config/CorsConfig.java new file mode 100644 index 0000000..a1d6029 --- /dev/null +++ b/src/main/java/asia/yulinling/workflow/config/CorsConfig.java @@ -0,0 +1,32 @@ +package asia.yulinling.workflow.config; + +import org.jetbrains.annotations.NotNull; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + *
+ * 跨域配置 + *
+ * + * @author YLL + * @since 2025/8/14 + */ +@Configuration +public class CorsConfig { + @Bean + public WebMvcConfigurer corsConfigurer() { + return new WebMvcConfigurer() { + @Override + public void addCorsMappings(@NotNull CorsRegistry registry) { + registry.addMapping("/**") + .allowedOriginPatterns("*") // 或指定 http://localhost:5173 + .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") + .allowedHeaders("*") + .allowCredentials(true); // 如果要发送 cookie + } + }; + } +} diff --git a/src/main/java/asia/yulinling/workflow/controller/AuthController.java b/src/main/java/asia/yulinling/workflow/controller/AuthController.java index 3f2bda9..050065d 100644 --- a/src/main/java/asia/yulinling/workflow/controller/AuthController.java +++ b/src/main/java/asia/yulinling/workflow/controller/AuthController.java @@ -13,9 +13,6 @@ import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -39,15 +36,11 @@ public class AuthController { private final AuthService authService; private final JwtUtil jwtUtil; - private final AuthenticationManager authenticationManager; + @PostMapping("/login") - public ApiResponse+ * 登录异常类 + *
+ * + * @author YLL + * @since 2025/8/14 + */ +public class LoginFailedException extends BaseException { + public LoginFailedException(Status status) { + super(status); + } + + public LoginFailedException(Integer code, String message) { + super(code, message); + } +} diff --git a/src/main/java/asia/yulinling/workflow/exception/handler/GlobalExceptionHandler.java b/src/main/java/asia/yulinling/workflow/exception/handler/GlobalExceptionHandler.java index 4fd4487..92cb479 100644 --- a/src/main/java/asia/yulinling/workflow/exception/handler/GlobalExceptionHandler.java +++ b/src/main/java/asia/yulinling/workflow/exception/handler/GlobalExceptionHandler.java @@ -1,5 +1,6 @@ package asia.yulinling.workflow.exception.handler; +import asia.yulinling.workflow.exception.LoginFailedException; import asia.yulinling.workflow.exception.PageException; import asia.yulinling.workflow.exception.ServiceException; import asia.yulinling.workflow.model.ApiResponse; @@ -30,7 +31,7 @@ public class GlobalExceptionHandler { * 统一 ServiceException 异常处理 * * @param e ServiceException - * @return 统一返回 json 格式 + * @return 统一返回 服务层 格式 */ @ExceptionHandler(ServiceException.class) @ResponseBody @@ -39,6 +40,19 @@ public class GlobalExceptionHandler { return ApiResponse.of(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage(), null); } + /** + * 统一 LoginFailedException 异常处理 + * + * @param e LoginFailedException + * @return 统一返回 登录异常 格式 + */ + @ExceptionHandler(LoginFailedException.class) + @ResponseBody + public ApiResponse> catchErrorHandler(LoginFailedException e) { + log.error("LoginFailedException error:{}", e.getMessage()); + return ApiResponse.ofException(e); + } + @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity@@ -17,9 +17,9 @@ public interface AuthService { /** * 登录系统 * - * @param authentication 登录信息 + * @param loginRequest 登录信息 */ - LoginVO login(Authentication authentication, boolean rememberMe); + LoginVO login(LoginRequest loginRequest); /** * 退出登录 diff --git a/src/main/java/asia/yulinling/workflow/service/impl/AuthServiceImpl.java b/src/main/java/asia/yulinling/workflow/service/impl/AuthServiceImpl.java index 0fe1d90..c888ccf 100644 --- a/src/main/java/asia/yulinling/workflow/service/impl/AuthServiceImpl.java +++ b/src/main/java/asia/yulinling/workflow/service/impl/AuthServiceImpl.java @@ -1,6 +1,9 @@ package asia.yulinling.workflow.service.impl; +import asia.yulinling.workflow.constant.Status; +import asia.yulinling.workflow.dto.request.LoginRequest; import asia.yulinling.workflow.dto.request.RegisterRequest; +import asia.yulinling.workflow.exception.LoginFailedException; import asia.yulinling.workflow.mapper.UserMapper; import asia.yulinling.workflow.model.entity.User; import asia.yulinling.workflow.model.vo.LoginVO; @@ -11,6 +14,8 @@ import asia.yulinling.workflow.utils.JwtUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; @@ -39,22 +44,31 @@ public class AuthServiceImpl implements AuthService { /** * 登录系统 * - * @param authentication 登录信息 + * @param loginRequest 登录信息 */ @Override - public LoginVO login(Authentication authentication, boolean rememberMe) { - UserPrincipal userPrincipal = (UserPrincipal) authentication.getPrincipal(); + public LoginVO login(LoginRequest loginRequest) { - String accessToken = jwtUtil.generateToken(authentication, rememberMe); - Long expiresIn = jwtUtil.getExpiresIn(rememberMe); + try { + Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken( + loginRequest.getUsername(), loginRequest.getPassword() + )); - log.info("用户登录成功: {}", userPrincipal.getUsername()); - return LoginVO.builder() - .userId(userPrincipal.getId()) - .username(userPrincipal.getUsername()) - .accessToken(accessToken) - .expiresIn(expiresIn) - .build(); + UserPrincipal userPrincipal = (UserPrincipal) authentication.getPrincipal(); + + String accessToken = jwtUtil.generateToken(authentication, loginRequest.getRememberMe()); + Long expiresIn = jwtUtil.getExpiresIn(loginRequest.getRememberMe()); + + log.info("用户登录成功: {}", userPrincipal.getUsername()); + return LoginVO.builder() + .userId(userPrincipal.getId()) + .username(userPrincipal.getUsername()) + .accessToken(accessToken) + .expiresIn(expiresIn) + .build(); + } catch (BadCredentialsException e) { + throw new LoginFailedException(Status.USERNAME_PASSWORD_ERROR); + } } /** diff --git a/src/test/java/asia/yulinling/workflow/service/EmailServiceTest.java b/src/test/java/asia/yulinling/workflow/service/EmailServiceTest.java index 2086989..b8ce0f7 100644 --- a/src/test/java/asia/yulinling/workflow/service/EmailServiceTest.java +++ b/src/test/java/asia/yulinling/workflow/service/EmailServiceTest.java @@ -3,7 +3,6 @@ package asia.yulinling.workflow.service; import asia.yulinling.workflow.WorkFlowMainTests; import cn.hutool.core.io.resource.ResourceUtil; import jakarta.mail.MessagingException; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired;