해결된 질문
작성
·
53
1
안녕하세요 선생님,
[커스텀 인증실패 핸들러 - AuthenticationFailureHandler (08:11) ] 강의를 듣다가 의문점이 생겨서 문의드립니다.
현재 AuthenticationFailureHandler 를 extend 해서 사용 중인데 FormAuthenticationFailureHandler.onAuthenticationFailure 메소드에서 아래처럼 defaultFailureUrl 을 변경하는 부분이 있습니다.
@Component
public class FormAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
String errorMessage = "Invalid Username or Password";
if (exception instanceof BadCredentialsException) {
errorMessage = "Invalid Username or Password";
} else if (exception instanceof UsernameNotFoundException) {
errorMessage = "User not exists";
} else if (exception instanceof CredentialsExpiredException) {
errorMessage = "Expired password";
} else if (exception instanceof SecretException) {
errorMessage = "Invalid Secret Key";
}
// Thread Safe...?
setDefaultFailureUrl("/login?error=true&exception=" + errorMessage);
super.onAuthenticationFailure(request, response, exception);
}
}
이 setDefaultFailureUrl 메소드를 호출해서 모든 쓰레드가 접근할 수 있는 defaultFailureUrl 필드를 변경하는 건 Thread Safe 하지 않지 않나요??
답변 1
0
setDefaultFailureUrl("/login?error=true&exception=" + errorMessage);
에서 변경되는 부분은 errorMessage 인데 이건 지역변수라 스레드마다 스택에 저장되기 때문에 동시성의 문제가 발생하지 않습니다
아 네 그렇군요
사실 defaultFailureUrl 자체는 기본 경로이기 때문에 말 그대로 하나의 경로를 가지고 공유하는 거라 동시성 이슈에서 문제가 되지 않는데 그 뒤의 errorMessage 를 사용한다고 하면 동시성 문제가 발생할 수 있겠네요
그렇다고 FormAuthenticationFailureHandler 를 스프링 빈이 아닌 일반 객체로 만들더라도 오직 하나만 생성되는 것은 동일하기 때문에 별 의미가 없기도 하네요
이 부분은 /login?error=true 까지만 하고 변경 요소는 추가하지 않는것이 안전해 보입니다.
다만 로그인 성공이 아닌 로그인 실패 같은 경우 동시성으로 문제가 될 만큼 동시적 접속이 문제가 될 것인지는 좀 고민이 필요해 보입니다.
예리한 지적 감사합니다.
답변 감사합니다.
일단 아래처럼 조금만 코드를 수정해서 실습 진행하겠습니다.
@Component("formAuthenticationFailureHandler")
public class FormAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
String errorMessage = "no-message";
if (exception instanceof BadCredentialsException) {
errorMessage = "Invalid Username or Password";
} else if (exception instanceof UsernameNotFoundException) {
errorMessage = "User not exists";
} else if (exception instanceof CredentialsExpiredException) {
errorMessage = "Expired password";
} else if (exception instanceof SecretException) {
errorMessage = "Invalid Secret Key";
}
getRedirectStrategy().sendRedirect(request, response, "/login?error=true&exception=" + errorMessage);
}
}
맞습니다. errorMessage 는 지역변수로 모든 쓰레드가 각자 갖고 사용합니다.
하지만 errorMessage 를 통해서 최종적으로 변경을 하는 defaultFailureUrl 은 모든 쓰레드가 접근할 수 있는 SimpleUrlAuthenticationFailureHandler 클래스의 필드입니다.