권한에 막혀 로그인이 요청되는 상황에는 security가 알아서 요청 페이지를 저장했다가, 로그인 성공 후 해당 페이지로 보내주지만
페이지1 → 로그인 페이지로 직접 이동 → 로그인 성공
순으로 진행되면 페이지1로 보내는 게 아니라 메인페이지로 보내진다.
왜냐면 내가 그렇게 설정해놔서..
이전 설정
Controller (관련 설정 없음. 안 봐도 됨)
...
public class HomeController {
...
@RequestMapping("/musicatlogin")
public String loginSubController(Model model, HttpServletRequest request) {
if(request.getParameter("email") != null ) {
//로그인 실패 시, 입력했던 email 추가(로그인 페이지에 노출하기 위해)
model.addAttribute(request.getParameter("email"));
}
return "view/member/login";
}
...
}
SecurityConfig
@Override
protected void configure(HttpSecurity http) throws Exception {
...
http
.formLogin()
.loginPage("/musicatlogin")
.loginProcessingUrl("/login")
...
.successHandler(new AuthenticationSuccessHandler() {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
...
//사용자 요청 페이지
RequestCache requestCache = new HttpSessionRequestCache();
SavedRequest savedRequest = requestCache.getRequest(request, response);
if(savedRequest != null) { //요청 페이지가 있으면 보낼 url
response.sendRedirect(savedRequest.getRedirectUrl());
} else { //요청페이지가 없으면 보낼 url
response.sendRedirect("/main");
}
}
})
.failureHandler(new AuthenticationFailureHandler() {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
//로그인 실패 예외 발생 시 처리
if (exception instanceof UsernameNotFoundException) {
request.setAttribute("loginFailMessage", "아이디 또는 비밀번호를 잘못 입력하였습니다.");
} else if {
...
}
//loginFailMessage 들고 로그인 페이지로 이동
RequestDispatcher dispatcher = request.getRequestDispatcher("/musicatlogin");
dispatcher.forward(request, response);
}
});
}
저 사용자 요청 페이지라는 것이 모든 상황에서의 요청 페이지를 저장하는 것이 아니라, security가 가로챈 경우(권한 확인을 위한 로그인처럼)에 해당하는 것임을 이제서야 알게 된 것...
사용자 요청을 security가 가로채서 로그인 하게 되는 경우에는
이렇게 리다이렉트 해줄 주소가 찍히지만,
직접 로그인하는 경우에는 NullPointerException이 발생하는 것을 확인하였다.
수정
관련해서 정보를 찾아보니 Session을 활용할 수 있었다.
이전 페이지 정보를 Referer에서 꺼내오고, 그걸 Session에 담아두었다가 성공하면 Session에서 파기시키는 방법
Controller
...
public class HomeController {
...
@RequestMapping("/musicatlogin")
public String loginSubController(Model model, HttpServletRequest request) {
//위와동일
//이전 페이지 정보 꺼내오기
String referer = request.getHeader("Referer");
//login페이지나 login 시도 주소가 아닌 경우 session에 "prevPage"로 저장
if(referer != null && !referer.contains("login")) {
request.getSession().setAttribute("prevPage", referer);
}
return "view/member/login";
}
...
}
SecurityConfig
@Override
protected void configure(HttpSecurity http) throws Exception {
...
http
//위와 동일
.successHandler(new AuthenticationSuccessHandler() {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
...
//사용자 요청 페이지(security가 요청을 가로챘을 때)
RequestCache requestCache = new HttpSessionRequestCache();
SavedRequest savedRequest = requestCache.getRequest(request, response);
String prevPage;
if(savedRequest != null) { //권한 확인을 위한 로그인일 경우 보낼 주소
prevPage = savedRequest.getRedirectUrl();
requestCache.removeRequest(request, response);
} else { //사용자가 직접 로그인 버튼을 눌러 진행한 로그인일 경우 보낼 주소
prevPage = (String) request.getSession().getAttribute("prevPage");
request.getSession().removeAttribute("prevPage");
}
response.sendRedirect(prevPage);
}
})
//위와 동일
});
}
이제 여러 번 실패하고 로그인을 해도, 어느 페이지에 있다가 로그인을 해도 이전 페이지로 돌아갈 수 있게 되었다.
+
security가 가로챈 경우에도 session에 저장하는 건지 확인해보니 맞음
이거 먼저 확인했으면.. 삽질을 좀 덜하지 않았을까..
'프로젝트 > 2' 카테고리의 다른 글
인증 성공 시 메서드 호출 위치 변경 (0) | 2022.06.27 |
---|---|
파일 (0) | 2022.06.25 |
댓글 (2) | 2022.06.16 |
Docker에 tomcat 올리기 (0) | 2022.06.08 |