강의

멘토링

커뮤니티

Cộng đồng Hỏi & Đáp của Inflearn

Hình ảnh hồ sơ của brewagebear
brewagebear

câu hỏi đã được viết

mùa xuân an ninh

12) Xử lý ngoại lệ và yêu cầu bộ lọc bộ đệm: ExceptionTranslationFilter,RequestCacheAwareFilter

인증 실패하지 않고 로그인할 경우 savedRequest

Viết

·

1.6K

3

안녕하세요! 

먼저 강의 너무 잘 듣고있습니다. 감사합니다.

이번 강의를 보는 중 의문점이 생겨 질문 남깁니다.
강의 마지막의 디버깅 과정에서 과정 부분입니다.

캐싱 과정 확인을 위해 인위적으로 /로 접근한 후 요청 정보를 캐시에 남기게 하고, login 페이지로 redirect 되게 하여 인증을 하여, 캐시에서 요청 정보를 가져와서 해당 경로로 이동하게 하였습니다.
(successHandler()를 통해서)

여기서 의문점이 생겼습니다. /로 접근하지 않고 바로 /login으로 접근해 요청 정보를 캐싱하지 않는 경우는 어떻게 될지가 궁금했습니다.

결과는 예상했던대로 savedRequest가 null이어서 에러가 났습니다.

그래서 제 결론은 이 요청 정보 캐싱 기능을 이용하는 경우, successHandler에서 바로 /login으로 접근하는 경우도 고려해서 구현해야 하는지, 아니면 successHandler 이 외에 자동 설정이나 다른 설정을 해야하는 것이 있는지 궁금합니다.

감사합니다!

spring-bootSpring Securityjava

Câu trả lời 5

5

leaven님의 프로필 이미지
leaven
Người chia sẻ kiến thức

먼저 아래쪽에 로시츠키 님께서 질문하신 "RequestCache와 savedRequest에 대해서" 에 대한 답변을 먼저 참조해 주시기 바랍니다.

요청 캐시 즉 RequestCache 는 그렇게 어려운 개념이 아니죠.

클라이언트가 요청 시 요청과정에서 발생하는 여러 정보들을 세션에 담아 두고 필요시 꺼내어 쓰기 위한 기능입니다.

유념할 점은 이 요청 캐시를 스프링 시큐리티가 언제, 어떤 이유로 사용하느냐를 이해하는 것이 중요합니다.

스프링 시큐리티에서는 SavedRequest 에 캐시용 데이터들을 담아 두고 이 객체를 세션에 저장하게 되는데 이 시점은 정확하게 인증에 실패할 때가 아닌 인증의 과정을 아예 거치지 않은 상태에서 인증 사용자에게만 허용되는 자원에 접근했다가  FilterSecurityInterceptor 필터에 의해서 접근이 거부되어 예외가 발생하게 되고 그 예외를 ExceptionTranslationFilter 가 받아서 처리하는 과정중에 requestCache.saveRequest(request, response) 처리가 이루어 진다는 점입니다.

그리고 이후에 사용자가 인증에 성공하게 되면 인증필터가 ExceptionTranslationFilter 에서 처리한 RequestCache 와 SavedRequest  객체를 참조해서 클라이언트가 원래 접근하고자 했던 자원의 정보를 얻어서 SuccessHandler 에서 리다이렉트 할 뿐 이러한 원리를 어떤 시점과 위치에서 활용하느냐는 개발자의 몫입니다.

그래서  /login 으로 바로 접근해서 인증에 성공하게 되면 RequestCache 와 SavedRequest  의 처리가 전혀 이루어지지 않기 때문에 당연히 savedRequest  는 null 일 수 밖에 없습니다.

즉 인증에 성공한 상태에서 자원에 접근할 경우 FilterSecurityInterceptor 가 접근을 거부하지 않을 것이고 그러면 예외가 발생하지 않으므로 ExceptionTranslationFilter 를 호출할 일이 없기 때문에 savedRequest  객체는 생성되지 않습니다.

savedRequest 는 FilterSecurityInterceptor 와 ExceptionTranslationFilter 의 과정에서 생성되는 객체임을 기억하시면 됩니다.

그렇다면 SuccesHandler 에서 savedRequest  가 null 인치 체크하는 구문이 필요하고 상황에 따른 분기 로직이 구현되어야 할 것입니다.

참고로 AuthenticationSuccessHanlder 의 구현체 중 스프링 시큐리티에서 제공하는SavedRequestAwareAuthenticationSuccessHandler 클래스가 있는데 소스를 보시면 다음과 같은 부분이 있습니다.

public class SavedRequestAwareAuthenticationSuccessHandler extends
SimpleUrlAuthenticationSuccessHandler {
protected final Log logger = LogFactory.getLog(this.getClass());

private RequestCache requestCache = new HttpSessionRequestCache();

@Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response, Authentication authentication)
throws ServletException, IOException {

SavedRequest savedRequest = requestCache.getRequest(request, response);

if (savedRequest == null) {
super.onAuthenticationSuccess(request, response, authentication);

return;
}

보시면 savedRequest == null 일 경우 부모 클래스인 SimpleUrlAuthenticationSuccessHandler 에서 처리하도록 위임합니다.

if (savedRequest == null) {
super.onAuthenticationSuccess(request, response, authentication);

return;
}

그래서 SimpleUrlAuthenticationSuccessHandler 에서 이부분을 어떻게 처리를 하고 있는지 소스를 분석해서 SuccessHandler 구현하실 때 참고하시면 될 것 같습니다.

아마 신수웅 님께서 질문하신 의도대로 스프링 시큐리티가 처리하고 있는 것 같습니다.

4

leaven님의 프로필 이미지
leaven
Người chia sẻ kiến thức

인증에 성공하게 되면 기본적으로 스프링 시큐리티가 SavedRequestAwareAuthenticationSuccessHandler 클래스를 사용합니다.

그래서 savedRequest 의 생성여부에 따른 대한 처리를 별도로 하실 필요가 없습니다.

다만 AuthenticationSuccessHandler 에서 특정한 로직을 처리해야 하거나 추가적인 기능을 사용해야 한다면 SavedRequestAwareAuthenticationSuccessHandler 클래스를 상속해서 기본기능은 부모클래스에게 맡기고 커스터마이징 할 부분을 별도로 처리하시면 될 것 같습니다.

예를 들어

public class CustomAuthenticationSuccessHandler 
extends SavedRequestAwareAuthenticationSuccessHandler {

@Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response, Authentication authentication)
throws ServletException, IOException {

// 추가로직 구현

로깅처리 ..
세션처리 ..
예외처리 ..
등등 ...

super.onAuthenticationSuccess(request, response, authentication);

}

그리고 SecurityConfig 클래스에서 

http.formLogin()

        .successHandler(new CustomAuthenticationHandler())

로 설정하시면 됩니다.

상황에 따라 여러 방안으로 구현하시면 됩니다

2

brewagebear님의 프로필 이미지
brewagebear
Người đặt câu hỏi

상세한 답변 정말 감사드립니다!
궁금증을 해소할 수 있었습니다.

추가적으로 간단한 질문을 드리자면, 
언급해주신 SavedRequestAwareAuthenticationSuccessHandler를 시큐리티 설정에서 주입받아 설정을 하면 되는 것인지,
이 Handler를 호출해 자동으로 처리 되는 부분이 있는 것인지 궁금합니다.
(예를 들면, 인증 예외가 발생해서 
savedRequest가 생성되는 경우, 인증 성공 후 이 Handler를 자동 호출한다던지??)

감사합니다!!

1

brewagebear님의 프로필 이미지
brewagebear
Người đặt câu hỏi

상세한 답변 정말 감사드립니다!!

정말 많은 도움이 됩니다~!!

0

"/login"으로 직접 url로 접근하여 인증처리하게 되면 왜 savedRequest가 null인지 이해를 못하겠습니다

 

제가 이해한 위에 내용 토대로 언제 인증을 하지 못해 requestCache되는 시점이 중요합니다. 근데 login url은 애초에 인증을  인증을 받는 페이지가 아닙니다. 즉 "닌 인증의 과정을 아예 거치지 않은 상태에서 인증 사용자에게만 허용되는 자원" 를 접근할때 requestCache에 저장된다고 이해하였습니다. 

 

위에 내용은 login로  바로 접근하게되어서 그전에 페이지가 없어서  null로 들어온걸로 이해하였습니다.

 

이 

Hình ảnh hồ sơ của brewagebear
brewagebear

câu hỏi đã được viết

Đặt câu hỏi