Spring Security 로그인 실패 시 에러메세지
by 볼빵빵오춘기Toy Project를 진행하면서 로그인과 회원가입 기능을 Security로 구현했지만, 로그인 시 아무런 안내 없이 실패하면 사용자는 이유를 알 수 없어 혼란스러울 수 있다.
그래서 로그인에 실패할 경우, 사용자에게 안내 문구를 제공해 왜 로그인이 되지 않는지 명확히 알려주는 것이 필요하다고 생각하게 됐다.
SecurityConfig
@Bean public LoginSuccessHandler loginSuccessHandler(){
return new LoginSuccessHandler();
}
@Bean
public LoginFailureHandler loginFailureHandler(){
return new LoginFailureHandler();
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception{
http.formLogin((formLogin) ->
formLogin.loginPage("/loginForm").loginProcessingUrl("/login").successHandler(loginSuccessHandler()).failureHandler(loginFailureHandler()))
.authorizeHttpRequests(authorize ->
authorize.requestMatchers("/admin/**").hasAnyRole("ADMIN") // /center/** url => admin 권한이 있는 사용자만 접근 가능
.anyRequest().permitAll() // 권한을 주지않은 url 이 아니면 접근 허용
).oauth2Login((oauth2) -> oauth2
.loginPage("/loginForm").userInfoEndpoint(userInfoEndpoint -> userInfoEndpoint
.userService(principalOauth2UserService)).successHandler(loginSuccessHandler()).failureHandler(loginFailureHandler()))
.exceptionHandling(exceptionHandling -> exceptionHandling
.authenticationEntryPoint(customAuthenticationEntryPoint()) // 인증되지 않은 사용자가 접근할 때 처리
.accessDeniedHandler(customAccessDeniedHandler())); // 권한이 없는 사용자가 접근할 때 처리
http.csrf(CsrfConfigurer::disable).cors(Customizer.withDefaults());
return http.build();
}
※ 설정 코드 부분(더보기 참고)
더보기
@Bean public LoginSuccessHandler loginSuccessHandler(){
return new LoginSuccessHandler();
}
@Bean
public LoginFailureHandler loginFailureHandler(){
return new LoginFailureHandler();
}
.userService(principalOauth2UserService)).successHandler(loginSuccessHandler()).failureHandler(loginFailureHandler()))
LoginSuccessHandler
로그인을 성공하면 SecurityContextHolder를 통해 인증된 사용자의 정보를 가져와 Authentication에 정보를 갖고있다.
@Component
public class LoginSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
public LoginSuccessHandler() {
// 로그인 성공 시 이동할 URL 설정
this.setDefaultTargetUrl("/");
}
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
// SecurityContextHolder를 통해 현재 인증된 사용자의 정보를 가져옴
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
super.onAuthenticationSuccess(request, response, authentication);
}
}
LoginFailureHandler
로그인 실패 시 어떤 Exception이 발생하는지 확인 후 그에 맞는 메세지를 출력하도록 한다.
@Configuration
public class LoginFailureHandler extends SimpleUrlAuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException {
String errorMessage = null;
if (exception instanceof BadCredentialsException) {
errorMessage = "아이디와 비밀번호를 확인해주세요.";
} else if (exception instanceof InternalAuthenticationServiceException) {
errorMessage = "내부 시스템 문제로 로그인할 수 없습니다. 관리자에게 문의하세요.";
} else if (exception instanceof UsernameNotFoundException) {
errorMessage = "존재하지 않는 계정입니다.";
} else {
errorMessage = "알 수없는 오류입니다.";
}
errorMessage = URLEncoder.encode(errorMessage, "UTF-8");
setDefaultFailureUrl("/loginForm?error=" + errorMessage);
super.onAuthenticationFailure(request, response, exception);
}
}
실행 결과
'👩🏻💻 About 프로그래밍 > spring' 카테고리의 다른 글
Spring boot 게시판 만들기(게시판 CRUD) (0) | 2024.08.13 |
---|---|
회원가입 유효성 검사 (0) | 2024.08.13 |
파일 업로드(하나 업로드 vs 여러 개 업로드) (0) | 2024.07.20 |
JPA 동적쿼리 사용해보기 (0) | 2024.07.19 |
JPA 정적쿼리, 동적쿼리(feat. JpaSpecificationExecutor) (0) | 2024.07.19 |
블로그의 정보
Hello 춘기's world
볼빵빵오춘기