프로젝트/2

[Security] 로그인 시 이전 페이지 띄우기

da77777 2022. 7. 31. 18:32

권한에 막혀 로그인이 요청되는 상황에는 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