Spring Security를 사용하면 로그인 30분뒤에 권한이 있지 않아 다른 페이지로 넘어가려고 하면 로그인 화면으로 넘어가게 된다. 다만 Ajax 같이 비동기식으로 통신을 하면 로그인 페이지로 넘어가지 않는다.
그래서 실제로 서버에서 값을 불러와야하는데 문제는 이미 세션이 만료되서 서버에 접근 할 수 없다는것!!
그렇다면 바인딩 되야할 데이터가 있었다면 바인딩 되지 않을 것이고... 다른 js 라이브러리를 사용 중이였다면 에러가 발생할 텐데... 이 문제를 해결해야 된다는것!
과정은 아래와 같다
Ajax 통신 -> 세션 만료시 -> 403 에러 전송 -> Ajax에서 403에러 시 login 화면 이동
일단 기본적인 ajax 세팅이다.
회원을 검사하는 ajax 코드가 있다고 가정하겠다.
$.ajax({
url: '/member/check',
type: 'POST',
data: {
number: value
},
success: (data) => {
성공시 코드...
}
});
ajax가 실행 될때 /member/check에 POST 요청을 보낼텐데 이때 로그인 세션이 만료 되었을때 403 에러를 전송 해야한다
public class AjaxAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint {
/**
* @param loginFormUrl URL where the login page can be found. Should either be
* relative to the web-app context path (include a leading {@code /}) or an absolute
* URL.
*/
public AjaxAuthenticationEntryPoint(String loginFormUrl) {
super(loginFormUrl);
}
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
String ajaxHeader = ((HttpServletRequest) request).getHeader("X-Requested-With");
boolean isAjax = "XMLHttpRequest".equals(ajaxHeader);
if (isAjax) {
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Ajax REquest Denied (Session Expired)");
} else {
super.commence(request, response, authException);
}
}
}
위 코드는 로그인 세션이 만료 되고나서 요청이 들어오게 되면 처리하는 클래스이다.
중간에서의 XMLHttpRequest의 문자열을 ajaxHeader와 비교한 이유는 ajax는 XMLHttpRequest를 사용하기 때문이다! 그래서 ajax인지 아닌지 isAjax라는 변수를 통해서 검사했다.
그리고 나서 ajax가 맞다면 response에 에러를 403 에러를 실어서 보내준다.
이렇게 클래스를 생성 했다면 설정을 담당하는 SecurityConfig 에 추가해 주도록하자!
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.exceptionHandling()
.authenticationEntryPoint(new AjaxAwareAuthenticationEntryPoint("/login"));
}
이제 마지막으로 할 것은 ajax에서 에러 메세지를 받아 403에러면 로그인 페이지로 보내주는 것이다.
$.ajax({
url: '/member/check',
type: 'POST',
data: {
number: value
},
success: (data) => {
isSuccess = data === true;
},error: (jqXHR) => {
if(jqXHR.status===403) {
alert("세션이 만료되었습니다");
location.replace("/login");
}
}
});
이렇게 하면 403에러를 받았을때 /login 페이지로 이동하게 된다!
끗!