1. 优化登录异常捕获
2. 添加跨域配置
This commit is contained in:
yulinling 2025-08-14 22:26:14 +08:00
parent 1e4ff3ce4d
commit 4a57799336
7 changed files with 100 additions and 27 deletions

View File

@ -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;
/**
* <p>
* 跨域配置
* </p>
*
* @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
}
};
}
}

View File

@ -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<LoginVO> login(@Valid @RequestBody LoginRequest loginRequest) {
Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(
loginRequest.getUsername(), loginRequest.getPassword()
));
LoginVO loginVO = authService.login(authentication, loginRequest.getRememberMe());
public ApiResponse<?> login(@Valid @RequestBody LoginRequest loginRequest) {
LoginVO loginVO = authService.login(loginRequest);
return ApiResponse.ofStatus(Status.LOGIN_SUCCESS, loginVO);
}

View File

@ -0,0 +1,21 @@
package asia.yulinling.workflow.exception;
import asia.yulinling.workflow.constant.Status;
/**
* <p>
* 登录异常类
* </p>
*
* @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);
}
}

View File

@ -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<ApiResponse<?>> handleValidationExceptions(
MethodArgumentNotValidException ex) {

View File

@ -1,9 +1,9 @@
package asia.yulinling.workflow.service;
import asia.yulinling.workflow.dto.request.LoginRequest;
import asia.yulinling.workflow.dto.request.RegisterRequest;
import asia.yulinling.workflow.model.vo.LoginVO;
import asia.yulinling.workflow.model.vo.RegisterVO;
import org.springframework.security.core.Authentication;
/**
* <p>
@ -17,9 +17,9 @@ public interface AuthService {
/**
* 登录系统
*
* @param authentication 登录信息
* @param loginRequest 登录信息
*/
LoginVO login(Authentication authentication, boolean rememberMe);
LoginVO login(LoginRequest loginRequest);
/**
* 退出登录

View File

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

View File

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