[스프링부트 게시판] 23. 로그인 실패 예외 처리

2022. 6. 28. 17:28·🚗 Backend Toy Project/스프링 부트 게시판

로그인 시스템을 구현했지만 사용자가 로그인을 성공했을 경우만 구현하였고, 실패했을 경우는 따로 구현하지 않아 사용자가 로그인을 실패해도 별다른 메시지도 없이 페이지가 리로드 되기만 하여 이 부분을 개선해주었습니다.

 

📝 1. SimpleUrlAuthenticationFailureHandler 클래스를 상속받는 커스텀 핸들러 구현

  • 로그인 실패와 관련된 예외는 HttpSecurity의 failureHandler()를 추가해주어야 캐치할 수 있다.
  • 해당 메서드는 AuthenticationFailureHandler 인터페이스 구현체를 파라미터로 받는다. 따라서 AuthenticationFailureHandler 인터페이스를 구현하는 클래스를 생성해야 하는데 여기서는 SimpleUrlAuthenticationFailureHandler를 상속받았다.
  • 그 이유는 해당 클래스에서 제공하는 setDefaultFailureUrl() 메서드를 사용하기 위해서이다.
  • 해당 메서드는 로그인 실패 시 요청되는 url을 지정할 수 있으며 이를 통해 Controller에서 객체를 받아 View 단으로 Model을 넘길 수 있다.
package com.cos.blog.handler;

@Component
public class UserLoginFailHandler extends SimpleUrlAuthenticationFailureHandler {

	@Override
	public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
			AuthenticationException exception) throws IOException, ServletException {
		
        String errorMessage;
        if (exception instanceof BadCredentialsException) {
            errorMessage = "아이디 또는 비밀번호가 맞지 않습니다. 다시 확인해 주세요.";
        } else if (exception instanceof InternalAuthenticationServiceException) {
            errorMessage = "내부적으로 발생한 시스템 문제로 인해 요청을 처리할 수 없습니다. 관리자에게 문의하세요.";
        } else if (exception instanceof UsernameNotFoundException) {
            errorMessage = "계정이 존재하지 않습니다. 회원가입 진행 후 로그인 해주세요.";
        } else if (exception instanceof AuthenticationCredentialsNotFoundException) {
            errorMessage = "인증 요청이 거부되었습니다. 관리자에게 문의하세요.";
        } else {
            errorMessage = "알 수 없는 이유로 로그인에 실패하였습니다 관리자에게 문의하세요.";
        }
        
        errorMessage = URLEncoder.encode(errorMessage, "UTF-8");
        setDefaultFailureUrl("/auth/loginForm?error=true&exception=" + errorMessage);
 
        super.onAuthenticationFailure(request, response, exception);
	}
}
여기서 errorMessage를 굳이 인코딩한 이유는 이후에 출력시킬 에러 메시지가 쿼리스트링 형태로 전달되도록 하였는데 errorMessage가 한글일 경우 정상적으로 출력되지 않기 때문이다. 따라서 수동으로 인코딩 해주어야 한다.

📝 2. SecurityConfig 클래스 수정

위에서 구현한 UserLoginFailHandler 클래스를 사용하기 위해 SecurityConfig 클래스에서 이를 DI하고 failureHandler() 메서드로 예외처리 핸들러를 지정해준다.

package com.cos.blog.config;

@Configuration //빈등록 (IoC관리)
@EnableWebSecurity //security 필터 등록
@EnableGlobalMethodSecurity(prePostEnabled = true) //특정 주소로 접근하면 권한 및 인증을 미리 체크하겠다는 뜻
@RequiredArgsConstructor
public class SecurityConfig {
	
    private final PrincipalDetailService principalDetailService;
    private final AuthenticationFailureHandler userLoginFailHandler;
    
    ...

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
          .csrf().disable()
          .authorizeRequests()  
            .antMatchers("/", "/auth/**", "/js/**", "/css/**", "/image/**")
            .permitAll()
            .anyRequest()
            .authenticated()
          .and()
            .formLogin()
            .loginPage("/auth/loginForm")
            .loginProcessingUrl("/auth/loginProc")
            .failureHandler(userLoginFailHandler)
            .defaultSuccessUrl("/");
        return http.build();
    }
}

📝 3. Controller 수정

다음으로 Controller에 구현되어 있는 로그인 요청 시 호출되는 메서드를 아래와 같이 수정해준다.

@GetMapping("/auth/loginForm")
public String loginForm(@RequestParam(value = "error", required = false) String error, 
			@RequestParam(value = "exception", required = false) String exception,
			Model model) {
	model.addAttribute("error", error);
	model.addAttribute("exception", exception);
	return "user/loginForm";
}

📝 4. View 수정

마지막으로 View 페이지에서 Model 객체를 받아 에러 발생 시 사용자에게 메시지를 발생시킬 수 있도록 구현한다.

<span> 
    <c:if test="${error}">
        <p id="valid" class="alert alert-danger">${exception}</p>
    </c:if>
</span>

📝 실행 결과


💡 알게 된 점

  • SimpleUrlAuthenticationFailureHandler를 통해 로그인 핸들러 설정하는 방법
 

GitHub - Daegwon-Kim/SpringBoot-JPA-Blog

Contribute to Daegwon-Kim/SpringBoot-JPA-Blog development by creating an account on GitHub.

github.com

 

저작자표시 (새창열림)

'🚗 Backend Toy Project > 스프링 부트 게시판' 카테고리의 다른 글

[스프링부트 게시판] 25. 회원가입시 validation 체크  (0) 2022.06.30
[스프링부트 게시판] 24. Remember Me 기능 구현  (0) 2022.06.29
[스프링부트 게시판] 22. 개선 및 수정사항  (0) 2022.06.25
[스프링부트 게시판] 21. 댓글 구현  (2) 2022.05.17
[스프링부트 게시판] 20. 카카오 로그인  (0) 2022.05.16
'🚗 Backend Toy Project/스프링 부트 게시판' 카테고리의 다른 글
  • [스프링부트 게시판] 25. 회원가입시 validation 체크
  • [스프링부트 게시판] 24. Remember Me 기능 구현
  • [스프링부트 게시판] 22. 개선 및 수정사항
  • [스프링부트 게시판] 21. 댓글 구현
Baeg-won
Baeg-won
  • Baeg-won
    좋았다면 추억이고 나빴다면 경험이다.
    Baeg-won
  • 전체
    오늘
    어제
    • 분류 전체보기
      • 🍃 Spring, Spring Boot
        • 스프링 프레임워크 기초
        • 스프링 핵심 원리 - 기본편
        • 자바 ORM 표준 JPA 프로그래밍 - 기본편
        • 스프링 MVC
        • 실전! 스프링 부트와 JPA 활용1 - 웹 애플리..
      • 🥑 Web Technoloy
      • 🚗 Backend Toy Project
        • 스프링 부트 게시판
        • Photogram
        • Baeg-won Clothing Gallery
      • 🥇 Problem Solving
        • Breadth-First Search
        • Depth-First Search
        • Backtracking
        • Simulation
        • Two-pointer
        • Binary Search
        • Greedy
        • Dynamic Programming
        • Minimum Spanning Tree
        • Dijkstra
        • Floyd warshall
      • ☕ Java
        • 명품 자바 에센셜
        • Applications
      • 🍦 JavaScript
        • JavaScript 기초
      • 🐧 Linux
        • 이것이 리눅스다(CentOS 8)
      • 📟 Database
        • 혼자 공부하는 SQL
      • 🧬 Data Structure
      • 🎬 HTML
      • 🎤 Tech Interview
      • 📌 etc
        • Unity 2D Raising Jelly Game
        • C++
        • 영어 쉐도잉
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
Baeg-won
[스프링부트 게시판] 23. 로그인 실패 예외 처리
상단으로

티스토리툴바