TIL&WIL
2023-07-26 TIL (RequestDispatcher)
blues_jun
2023. 7. 26. 21:33
오늘 공부한 내용
- 프로그래머스 알고리즘 문제풀이
- 내배캠 강의
- 내일배움캠프 플러스 주차 과제 (회원가입, 로그인 기능 추가)
알게된 내용
나는 로그인 기능을 UsernamePasswordAuthenticationFilter를 상속받는 JwtAuthenticationFilter에서 구현했다.
처음 필터를 배울 때에는 컨트롤러 앞단에서 기능을 수행하기 때문에 서로 소통을 할 수 없는줄 알고 있었고, 로그인 성공과 실패를 프론트를 구현해야 확인할 수 있는 줄 알았다.
그래도 과제의 결과물 때문에 성공과 실패를 알려줘야해서 처음에는 HttpServletResponse의 sendRedirect() 메서드를 활용해서 로그인이 실패했다는 것을 컨트롤러에 반환했다.
@Override
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
response.setStatus(HttpStatus.UNAUTHORIZED.value());
response.getWriter().write("로그인에 실패했습니다.");
response.sendRedirect("/api/user/login/fail"); // 로그인이 실패했다는 것을 컨트롤러에 반환하기 위해서 사용
}
@GetMapping("/user/login/fail")
public ResponseEntity<ApiResponseDto> failLogin() {
ApiResponseDto apiResponseDto = new ApiResponseDto("로그인에 실패했습니다. 아이디 및 비밀번호를 확인해주세요.", HttpStatus.UNAUTHORIZED.value());
return new ResponseEntity<>(
apiResponseDto,
HttpStatus.UNAUTHORIZED
);
}
여기서 문제점은 필터에서 status를 설정해도 정보가 컨트롤러에 넘어가지 않는다.
response.sendRedirect()를 호출하면, 브라우저는 지정된 경로로 다시 요청을 보내기 때문에 컨트롤러로 직접 실패 정보를 전달할 수 없는 것이다.
여러 정보를 찾아보다가 필터에서 컨트롤러에 실패 정보를 전달하기 위해서는 RequestDispatcher를 사용해야 한다고 했다.
RequestDispatcher
- RequestDispatcher은 현재 요청과 응답을 유지한 채로 다른 서블릿이나 JSP로 디스패치 한다.
- 즉, 컨트롤러에 실패정보를 전달하기 위해서는 RequestDispatcher를 이용해서 컨트롤러로 포워딩하는 방식을 사용하면 된다.
//로그인이 실패하는 경우 호출되는 메서드
@Override
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
request.setAttribute("message", "로그인에 실패했습니다. 아이디와 비밀번호를 확인 해주세요.");
RequestDispatcher dispatcher = request.getRequestDispatcher("/api/user/login/fail");
dispatcher.forward(request, response);
}
@PostMapping("/user/login/fail")
public ResponseEntity<ApiResponseDto> loginFail(HttpServletRequest request) {
String errorMessage = (String) request.getAttribute("message");
ApiResponseDto apiResponseDto = new ApiResponseDto(errorMessage, HttpStatus.UNAUTHORIZED.value());
// 상태 코드와 에러 메시지를 ResponseEntity에 담아서 반환
return new ResponseEntity<>(
apiResponseDto,
HttpStatus.UNAUTHORIZED
);
}
포스트맨 확인 결과는
원하는 결과가 나왔다.
이 방법이 좋은 방법인지는 모르겠지만 일단 원하던 결과에 맞게 구현이 되어서 다행이다..
더 많이 공부하자