Spring Async 사용시 SecurityContext Thread 전파 오류 (일시적 수정)

xlwdn·2022년 10월 20일
0

Async Annotation을 사용하여 여러 multipartfile을 s3에 처리하는 기능을 포함하고 있는 Company Entity 생성 함수를 비동기로 실행하도록 처리하였습니다.


@Async
override fun companySignup(req: CompanySignupRequest, emailCheckCode: String, companyIntroduction: CompanyIntroductionRequest) {
    if (checkEmail(req.companyContact.email, emailCheckCode)) {

		...   

}

그러나 test하던 중 API 자체는 200이 떴으나, 입력 값이 제대로 들어가지 않음을 확인할 수 있었습니다.

(Company는 User를 상속받고 있었으며, Inheritance 전략으로 Joined를 사용하였으나 위 API를 통해서 생성된 Company Entity는 User table에는 제대로 입력되었으나, Company 테이블에 제대로 데이터가 삽입되지 않았습니다. )

(아마도 Jpa autiditng하는 과정에서 getCurrentAuditor → SecurityContext를 참조하지 못하여 발생한 문제인 것 같습니다.)

에러가 발생한 곳 로그를 확인해보니, 아래와 같은 메시지를 throw 하고 있었습니다.

2022-10-05 22:23:59.562  INFO 1 --- [  XNIO-1 task-3] o.springdoc.api.AbstractOpenApiResource  : Init duration for springdoc-openapi is: 198 ms
2022-10-05 22:25:01.905 ERROR 1 --- [AsyncExecutor-3] .a.i.SimpleAsyncUncaughtExceptionHandler : Unexpected exception occurred invoking async method: public void ...

java.lang.NullPointerException: Cannot invoke "org.springframework.security.core.Authentication.getCredentials()" because the return value of "org.springframework.security.core.context.SecurityContext.getAuthentication()" is null

문제 해결


@Async 선언으로 병렬처리를 통한 비동기 작업을 수행할 때 기본적으로 threadHolder에 저장 후 사용하는 SecurityContext를 활용할 수 없어 이러한 문제가 발생했습니다.

하지만 이번 에러 같은 경우는 계정 생성 API이기 때문에 SecurityContext를 불러올 이유가 딱히 없어 굳이 SecurityContext를 전파시키는 방법으로 해결하지 않았습니다.

@Configuration
@EnableJpaAuditing
class AuditorAwareConfiguration: AuditorAware<Long> {

    override fun getCurrentAuditor(): Optional<Long> {
				====
				//수정 전
        SecurityContextHolder.getContext().authentication.credentials?.let {
				//수정 후
        SecurityContextHolder.getContext().authentication?.credentials?.let {
				====
            if (it == "") return Optional.empty()
            return Optional.of(it.toString().toLong())
        }?: return Optional.empty()
    }

}

throw된 에러는 NPE이기 때문에 kotlin에서 java lib를 사용할 때 nullable 처리만 제대로 해주었다면 발생하지 않았을 문제입니다.

0개의 댓글