새소식

반응형
Java/Spring

Spring Security 6 에서 AuthenticationSuccessHandler redirect Url 설정

  • -
반응형

Spring Security 6 에서 AuthenticationSuccessHandelr 를 Implements 하고 Extends 하고 있는 

SavedRequestAwareAuthenticationSuccessHandler 기본 클래스이다.

 

Spring Security 에서 기본적으로 사용하고 있는 클래스를 사용하면서 로그인 성공 시 

간단하게 필요한 URL 로 항상 Redirect 하는 방법을 알아보자.

 

기본 인증 과정은 아래와 같다.

Spring Security 6 이고 기본 FormLogin 설정 Filter 인 UsernamePasswordAuthenticationFilter 클래스를

사용하지 않고 Custom Filter 클래스를 만들었다.

그리고 실질적인 로그인정보를 비교하는 AuthenticationProvider 를 구현하여 AuthenticationCustomProvider 를

만들었고 AuthenticationSuccessHandler 를 구현하고 상속한 SavedRequestAwareAuthenticationSuccessHandler를

사용했다.

 

AuthenticationCustomSuccessHandler 는 아래와 같다.

public class AuthenticationCustomSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
	
	private final SecurityContextRepository securityContextRepository;
	private final SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder.getContextHolderStrategy();
	
	public AuthenticationCustomSuccessHandler(SecurityContextRepository securityContextRepository) {
		this.securityContextRepository = securityContextRepository;
	}
	
	@Override
	public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
			Authentication authentication) throws ServletException, IOException {
		
		SecurityContext securityContext = this.securityContextHolderStrategy.createEmptyContext();
		securityContext.setAuthentication(authentication);
		this.securityContextRepository.saveContext(securityContext, request, response);
		
		super.setAlwaysUseDefaultTargetUrl(true);
		super.setDefaultTargetUrl(request.getContextPath() + "/test/main");
		
		super.onAuthenticationSuccess(request, response, authentication);
	}
}

 

 

private final SecurityContextRepository securityContextRepository;
private final SecurityContextHolderStrategy securityContextHolderStrategy =
SecurityContextHolder.getContextHolderStrategy();

 

Spring Security 6 로 넘어가면서 바뀐점은 인증된 객체인 Authentication 의 저장하는 방법이다.

Spring Security 5 버전은 SecurityContextPersistenceFilter 가 ThreadLocal  에 직접 접근하여

SecurityContext 를 로드 + 설정 + 저장한다.

 

SecurityContextPersistenceFilter 인증 처리 과정

  1. 요청이 들어오면 SecurityContextRepository.loadContext() 를 호출해서 기존 인증 정보를 로딩한다.
    => 인증정보가 들어있는 SecurityContext를 가져옴
  2. 로딩된 SecurityContext를 SecurityContextHolderStrategy.setContext() 로 ThreadLocal 에 저장함
    => SecurityContextHolderStrategy 는 실제로 ThreadLocalSecurityContextHolderStrategy 클래스 사용
  3. 이후 필터 체인에서 인증 처리(UsernamePasswordAuthenticationFilter 등)가 해당 Context 사용
  4. 요청이 끝나면 finally 에서 SecurityContextHolderStrategy.getContext() 를 호출하여
    해당 SecurityContext 를 가져와 SecurityContextRepository 에 saveContext() 한다.
  5. SecurityContextHolderStrategy.clearContext() 를 통해 ThreadLocal 을 비운다.

 

Spring Security 6 로 변경되면서 관리하는 방법이

SecurityContextRepository 에 Context 를 저장하고 SecurityContextHolderStrategy 전략을

사용하면서 저장하는 방법 등 관리한다.

 

SecurityContextRepository 는 기본적으로 HttpSessionSecurityContextRepository 를 사용한다.

 

SecurityContext securityContext = this.securityContextHolderStrategy.createEmptyContext();
securityContext.setAuthentication(authentication);
this.securityContextRepository.saveContext(securityContext, request, response);

 

SecurityContextHolderStrategy 전략을 통해 새로운 SecurityContext 를 생성한다.

 

기본적으로 THREAD_LOCAL 방식을 사용한다.

값이 설정되어 있지 않으면 기본값으로 ThreadLocal 방식으로 설정한다.

아래는 SecurityContextHolder 클래스의 코드이다.

 

ThreadLocal  방식의 클래스는 ThreadLocalSecurityContextHolderStrategy 클래스이다.

.createEmptyContext() 함수를 호출하게 되면 SecurityContext 를 구현한 SecurityContextImpl 인스턴스로 리턴한다.

 

새로 생성한 SecurityContext 에 인증된 객체인 Authentication 를 설정한다.

그리고 SecurityContext 를 SecurityContextRepository 에 저장한다.

 

 

super.setAlwaysUseDefaultTargetUrl(true);
super.setDefaultTargetUrl(request.getContextPath() + "/test/main");

super.onAuthenticationSuccess(request, response, authentication);

 

setAlwaysUseDefaultTargetUrl 설정이 true 일 경우 항상 DefaultTargetUrl 로 설정된 url 로 이동하라는 뜻이다.

기본값은 false 이다.

본인은 true 로 했기 때문에 인증에 성공했을 경우 setDefaultTargetUrl 로 설정한 /test/main 으로 이동한다.

 

반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.