Skip to content

Commit 1cb31a9

Browse files
authored
♻️ [refactor] 커스텀 예외처리 적용 (#62)
* 🐛 fix: OAuth 인증 후 리다이렉트 경로 수정 * ♻️ refactor: 로그인 성공 응답을 인증 정보 조회 응답으로 통일 * ♻️ refactor: 커스텀 예외처리 적용 * chore: Java 스타일 수정 * ♻️ refactor: 리다이렉트 문자열 변수로 분리 * 🔧 chore: http-only 속성 추가 * 🔧 chore: session timeout 속성 추가 * ♻️ refactor: SecurityUtils 커스텀 예외처리 적용 * chore: Java 스타일 수정 --------- Co-authored-by: github-actions <>
1 parent f45fd3b commit 1cb31a9

File tree

12 files changed

+85
-43
lines changed

12 files changed

+85
-43
lines changed

backend/src/main/java/io/f1/backend/domain/admin/app/AdminDetailService.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import io.f1.backend.domain.admin.dao.AdminRepository;
44
import io.f1.backend.domain.admin.dto.AdminPrincipal;
55
import io.f1.backend.domain.admin.entity.Admin;
6+
import io.f1.backend.global.exception.errorcode.AdminErrorCode;
67

78
import lombok.RequiredArgsConstructor;
89

@@ -23,7 +24,9 @@ public UserDetails loadUserByUsername(String username) throws UsernameNotFoundEx
2324
adminRepository
2425
.findByUsername(username)
2526
.orElseThrow(
26-
() -> new UsernameNotFoundException("E404007: 존재하지 않는 관리자입니다."));
27+
() ->
28+
new UsernameNotFoundException(
29+
AdminErrorCode.ADMIN_NOT_FOUND.getMessage()));
2730
// 프론트엔드로 내려가지 않는 예외
2831
return new AdminPrincipal(admin);
2932
}

backend/src/main/java/io/f1/backend/domain/admin/app/handler/AdminLoginFailureHandler.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.fasterxml.jackson.databind.ObjectMapper;
44

55
import io.f1.backend.domain.admin.dto.AdminLoginFailResponse;
6+
import io.f1.backend.global.exception.errorcode.AuthErrorCode;
67

78
import jakarta.servlet.http.HttpServletRequest;
89
import jakarta.servlet.http.HttpServletResponse;
@@ -31,7 +32,9 @@ public void onAuthenticationFailure(
3132
response.setContentType("application/json;charset=UTF-8");
3233

3334
AdminLoginFailResponse errorResponse =
34-
new AdminLoginFailResponse("E401005", "아이디 또는 비밀번호가 일치하지 않습니다.");
35+
new AdminLoginFailResponse(
36+
AuthErrorCode.LOGIN_FAILED.getCode(),
37+
AuthErrorCode.LOGIN_FAILED.getMessage());
3538

3639
response.getWriter().write(objectMapper.writeValueAsString(errorResponse));
3740
}

backend/src/main/java/io/f1/backend/domain/admin/app/handler/AdminLoginSuccessHandler.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import io.f1.backend.domain.admin.dao.AdminRepository;
77
import io.f1.backend.domain.admin.dto.AdminPrincipal;
88
import io.f1.backend.domain.admin.entity.Admin;
9+
import io.f1.backend.global.exception.CustomException;
10+
import io.f1.backend.global.exception.errorcode.AdminErrorCode;
911

1012
import jakarta.servlet.http.HttpServletRequest;
1113
import jakarta.servlet.http.HttpServletResponse;
@@ -36,7 +38,7 @@ public void onAuthenticationSuccess(
3638
Admin admin =
3739
adminRepository
3840
.findByUsername(principal.getUsername())
39-
.orElseThrow(() -> new RuntimeException("E404007: 존재하지 않는 관리자입니다."));
41+
.orElseThrow(() -> new CustomException(AdminErrorCode.ADMIN_NOT_FOUND));
4042

4143
admin.updateLastLogin(LocalDateTime.now());
4244
adminRepository.save(admin);

backend/src/main/java/io/f1/backend/domain/user/api/SignupController.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package io.f1.backend.domain.user.api;
22

3+
import io.f1.backend.domain.auth.dto.CurrentUserAndAdminResponse;
34
import io.f1.backend.domain.user.app.UserService;
45
import io.f1.backend.domain.user.dto.SignupRequest;
5-
import io.f1.backend.domain.user.dto.SignupResponse;
66

77
import jakarta.servlet.http.HttpSession;
88

@@ -21,9 +21,9 @@ public class SignupController {
2121
private final UserService userService;
2222

2323
@PostMapping("/signup")
24-
public ResponseEntity<SignupResponse> completeSignup(
24+
public ResponseEntity<CurrentUserAndAdminResponse> completeSignup(
2525
@RequestBody SignupRequest signupRequest, HttpSession httpSession) {
26-
SignupResponse response = userService.signup(httpSession, signupRequest);
26+
CurrentUserAndAdminResponse response = userService.signup(httpSession, signupRequest);
2727
return ResponseEntity.status(HttpStatus.CREATED).body(response);
2828
}
2929
}

backend/src/main/java/io/f1/backend/domain/user/app/UserService.java

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,16 @@
22

33
import static io.f1.backend.domain.user.constants.SessionKeys.OAUTH_USER;
44
import static io.f1.backend.domain.user.constants.SessionKeys.USER;
5-
import static io.f1.backend.domain.user.mapper.UserMapper.toSignupResponse;
65

6+
import io.f1.backend.domain.auth.dto.CurrentUserAndAdminResponse;
77
import io.f1.backend.domain.user.dao.UserRepository;
88
import io.f1.backend.domain.user.dto.AuthenticationUser;
99
import io.f1.backend.domain.user.dto.SignupRequest;
10-
import io.f1.backend.domain.user.dto.SignupResponse;
10+
import io.f1.backend.domain.user.dto.UserPrincipal;
1111
import io.f1.backend.domain.user.entity.User;
12+
import io.f1.backend.global.exception.CustomException;
13+
import io.f1.backend.global.exception.errorcode.AuthErrorCode;
14+
import io.f1.backend.global.exception.errorcode.UserErrorCode;
1215
import io.f1.backend.global.util.SecurityUtils;
1316

1417
import jakarta.servlet.http.HttpSession;
@@ -25,7 +28,7 @@ public class UserService {
2528
private final UserRepository userRepository;
2629

2730
@Transactional
28-
public SignupResponse signup(HttpSession session, SignupRequest signupRequest) {
31+
public CurrentUserAndAdminResponse signup(HttpSession session, SignupRequest signupRequest) {
2932
AuthenticationUser authenticationUser = extractSessionUser(session);
3033

3134
String nickname = signupRequest.nickname();
@@ -34,36 +37,38 @@ public SignupResponse signup(HttpSession session, SignupRequest signupRequest) {
3437

3538
User user = initNickname(authenticationUser.userId(), nickname);
3639
updateSessionAfterSignup(session, user);
40+
3741
SecurityUtils.setAuthentication(user);
42+
UserPrincipal userPrincipal = SecurityUtils.getCurrentUserPrincipal();
3843

39-
return toSignupResponse(user);
44+
return CurrentUserAndAdminResponse.from(userPrincipal);
4045
}
4146

4247
private AuthenticationUser extractSessionUser(HttpSession session) {
4348
AuthenticationUser authenticationUser =
4449
(AuthenticationUser) session.getAttribute(OAUTH_USER);
4550
if (authenticationUser == null) {
46-
throw new RuntimeException("E401001: 로그인이 필요합니다.");
51+
throw new CustomException(AuthErrorCode.UNAUTHORIZED);
4752
}
4853
return authenticationUser;
4954
}
5055

5156
private void validateNicknameFormat(String nickname) {
5257
if (nickname == null || nickname.trim().isEmpty()) {
53-
throw new RuntimeException("E400002: 닉네임은 필수 입력입니다.");
58+
throw new CustomException(UserErrorCode.NICKNAME_EMPTY);
5459
}
5560
if (nickname.length() > 6) {
56-
throw new RuntimeException("E400003: 닉네임은 6글자 이하로 입력해야 합니다.");
61+
throw new CustomException(UserErrorCode.NICKNAME_TOO_LONG);
5762
}
5863
if (!nickname.matches("^[가-힣a-zA-Z0-9]+$")) {
59-
throw new RuntimeException("E400004: 한글, 영문, 숫자만 입력해주세요.");
64+
throw new CustomException(UserErrorCode.NICKNAME_NOT_ALLOWED);
6065
}
6166
}
6267

6368
@Transactional(readOnly = true)
6469
public void validateNicknameDuplicate(String nickname) {
6570
if (userRepository.existsUserByNickname(nickname)) {
66-
throw new RuntimeException("E409001: 중복된 닉네임입니다.");
71+
throw new CustomException(UserErrorCode.NICKNAME_CONFLICT);
6772
}
6873
}
6974

@@ -72,7 +77,7 @@ public User initNickname(Long userId, String nickname) {
7277
User user =
7378
userRepository
7479
.findById(userId)
75-
.orElseThrow(() -> new RuntimeException("E404001: 존재하지 않는 회원입니다."));
80+
.orElseThrow(() -> new CustomException(UserErrorCode.USER_NOT_FOUND));
7681
user.updateNickname(nickname);
7782

7883
return userRepository.save(user);
@@ -88,7 +93,7 @@ public void deleteUser(Long userId) {
8893
User user =
8994
userRepository
9095
.findById(userId)
91-
.orElseThrow(() -> new RuntimeException("E404001: 존재하지 않는 회원입니다."));
96+
.orElseThrow(() -> new CustomException(UserErrorCode.USER_NOT_FOUND));
9297
userRepository.delete(user);
9398
}
9499

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,28 @@
11
package io.f1.backend.domain.user.app.handler;
22

3+
import com.fasterxml.jackson.databind.ObjectMapper;
4+
5+
import io.f1.backend.global.exception.errorcode.AuthErrorCode;
6+
37
import jakarta.servlet.http.HttpServletRequest;
48
import jakarta.servlet.http.HttpServletResponse;
59

10+
import lombok.RequiredArgsConstructor;
11+
612
import org.springframework.security.core.AuthenticationException;
713
import org.springframework.security.web.AuthenticationEntryPoint;
814
import org.springframework.stereotype.Component;
915

1016
import java.io.IOException;
17+
import java.util.HashMap;
18+
import java.util.Map;
1119

1220
@Component
21+
@RequiredArgsConstructor
1322
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
1423

24+
private final ObjectMapper objectMapper;
25+
1526
@Override
1627
public void commence(
1728
HttpServletRequest request,
@@ -20,6 +31,11 @@ public void commence(
2031
throws IOException {
2132
response.setContentType("application/json;charset=UTF-8");
2233
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // 401
23-
response.getWriter().write("{\"error\": \"Unauthorized\"}");
34+
35+
Map<String, String> errorResponse = new HashMap<>();
36+
errorResponse.put("code", AuthErrorCode.UNAUTHORIZED.getCode());
37+
errorResponse.put("message", AuthErrorCode.UNAUTHORIZED.getMessage());
38+
39+
objectMapper.writeValue(response.getWriter(), errorResponse);
2440
}
2541
}

backend/src/main/java/io/f1/backend/domain/user/app/handler/OAuthSuccessHandler.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@ public void onAuthenticationSuccess(
2525
response.setContentType("application/json;charset=UTF-8");
2626

2727
if (principal.getUserNickname() == null) {
28-
getRedirectStrategy().sendRedirect(request, response, "/signup");
28+
String SIGNUP_REDIRECT_URL = "http://localhost:3000/signup";
29+
getRedirectStrategy().sendRedirect(request, response, SIGNUP_REDIRECT_URL);
2930
} else {
30-
getRedirectStrategy().sendRedirect(request, response, "/room");
31+
String MAIN_REDIRECT_URL = "http://localhost:3000/room";
32+
getRedirectStrategy().sendRedirect(request, response, MAIN_REDIRECT_URL);
3133
}
3234
}
3335
}

backend/src/main/java/io/f1/backend/domain/user/dto/SignupResponse.java

Lines changed: 0 additions & 3 deletions
This file was deleted.

backend/src/main/java/io/f1/backend/domain/user/mapper/UserMapper.java

Lines changed: 0 additions & 13 deletions
This file was deleted.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package io.f1.backend.global.exception.errorcode;
2+
3+
import lombok.Getter;
4+
import lombok.RequiredArgsConstructor;
5+
6+
import org.springframework.http.HttpStatus;
7+
8+
@Getter
9+
@RequiredArgsConstructor
10+
public enum AdminErrorCode implements ErrorCode {
11+
ADMIN_NOT_FOUND("E404007", HttpStatus.NOT_FOUND, "존재하지 않는 관리자 입니다");
12+
13+
private final String code;
14+
15+
private final HttpStatus httpStatus;
16+
17+
private final String message;
18+
}

0 commit comments

Comments
 (0)