401 - Full authentication is required to access this resource
org.springframework.security.access.AccessDeniedException: Access Denied
최근에 팀 프로젝트 진행하면서 Long polling을 이용하여 알림기능을 구현하였다.
이 과정에서 DeferredResult와 Spring security 같이 사용하게 되었는데, 요청 시에는 정상적으로 인증이 되었어도 응답 시에 401 Unauthorized가 반환되는 상황이 발생했다.
이슈가 발생했던 코드는 아래와 같다.
@GetMapping(value = "/subscribe")
public DeferredResult<List<NotificationResponse>> getNewNotifications(Principal principal) {
// 사용자 정보 가져오기
Member member = memberService.getMemberByUsername(principal.getName());
// DeferredResult 생성 및 저장소에 저장
DeferredResult<List<NotificationResponse>> deferredResult =
notificationService.getDeferredResult(member.getId().toString());
deferredResult.onTimeout(() -> {
deferredResult.setErrorResult(new NoMoreNotificationException());
});
return deferredResult;
}
원인을 파악하기 위해 일주일이라는 정말 많은 시간이 소요 되었다.
그만큼 원인을 파악하기 힘들었는데, 그 과정을 조금 공유해볼까 한다.
처음에는 단순히 비동기 처리 시 SecurityContext가 자식 스레드에 전파되지 않아서 발생한 문제로 파악했었다.
DeferredResult는 비동기로 요청을 처리해야할 때 사용되는데, 이로 인해 중간에 SecurityContext를 잃어버려 발생하는 이슈로 짐작을 하고 있었다.
DelegatingSecuritContextRunnable/Callable
DelegatingSecurityContextRunnable
를 사용하여 비동기 처리 시에도 해당 스레드에도 SecurityContext를 전파할 수 있다.
그렇기에 아래와 같이 코드를 작성하여 SecurityContext 전파를 시도하였지만, 해결책이 되지는 못했다.