개발/Spring Security

Authentication of controller parameters is null using Spring security

Debin 2022. 9. 21.
반응형

제목이 너무 길어져서 영어로 한 번(?) 써봤습니다.

번역하면 스프링 시큐리티를 사용할 때 스프링 MVC 컨트롤러에 파라미터로 Authentication이 null로 들어온다!

바로 시작하겠습니다.

 

스프링 시큐리티와 스프링 MVC를 사용하면 다음과 같이 Authentication을 파라미터로 받을 수 있다는 내용이 굉장히 많다.

 

현재 메서드

그러나 필자의 디버깅을 통해서는 authentication은 계속 null 값만 들어온다. 이번에는 이를 해결한 과정을 적어보려고 한다.

굉장히 간단하다. 일단 아래와 같이 검색을 해보았다. (어설픈 영어 실력은 덤)

 

그랬더니 아래와 같은 클래스가 눈에 띄였다. AuthenticationPrincipalArgumentResolver!!!!

바로 인텔리제이에 들어가서 검색을 해보았다.

크게 3가지 정도가 나오는데 하나는 Deprecated 되었고, 하나는 WebFlux에서 사용하는 클래스였다.

본인이 추측하기로는 결국 필자가 사용해야할 클래스는 아래 클래스다.

 

그래서 이것이 동작하나 디버깅을 해봤는데 역시나 사용되지 않았다.

그럼 제일 먼저 할 일은 이것을 작동하게 객체를 스프링 빈으로 등록해야 된다는 생각이 들었다.

 

참고로 공식문서에서는 @EnableWebSecurity를 사용하면 자동으로 등록되서 사용이 가능하다는데 왜 안되는지 의문이 들었다.

(어디 설정을 잘 못 건드린건가..)

 

일단 아래 코드를 통해 ArgumentResolver를 등록했다.

 

그럼 이제 해결인가?? 싶었는데..

등록한 ArgumentResolver는 동작하지만 결정적으로 Authentication 객체가 파라미터로 넘어오지는 않았다.

다시 디버깅을 통해 살펴보았다.

AuthenticationPrincipalArgumentResolver 클래스의 resolveArgument 메서드 안에는 다음과 같은 부분이 있다.

 

디버깅을 해보면 여기서 지금 null이 리턴되고 있는데, principal은 null이 아니었다.

아마 !ClassUtils.isAssignable(parameter.getParameterType(), principal.getClass())

이 값이 참이여서 그런 것 같다.

이 메서드는 principal.getClass()가 parameter.getParameterType()으로 캐스팅 되는지 참, 거짓을 확인하는 메서드다.

결국 지금 캐스팅이 안되므로 null이 리턴되는 것 같다.

 

현재 상황은 다음과 같다.

 

  • principal.getClass() == String
  • parameter.getParameterType() == Authentication

따라서 캐스팅이 안되므로 오류가 발생한 것 같다. 그럼 이제 pricincipal에 변수에 담는 인스턴스를 변경하면 될 것 같다.

생각해보면 현재 데이터베이스와 연동하여 개발중인데, 사실 엔티티의 ID(PK, Long 클래스)만 있으면 될 것 같다.

Authentication은 필요 없을 것 같고, principal에 Authentication을 담는게 이상하다.

그래서 아래와 같이 컨트롤러를 수정했다.

 

그리고 이제 Authenticaion을 구현한 클래스의 생성자에서 principal 값으로 모두 엔티티의 id(Long class)를 넣었다.

 

그리고 다시 디버깅을 해보았다. 과연 결과는..?!

 

id 값이 정상적으로 넘어오는 것을 확인할 수 있다!! 이렇게 문제 해결!!

꽤나 뿌듯한 느낌이 든다. 역시 디버깅은 매우 중요한 것 같고, 무엇인 문제인지 빠르게 발견하는 통찰력(?)도 중요한 것 같다.

조금은 실력이 발전한 것 같다. 굳굳.

 

이상으로 포스팅을 마칩니다. 감사합니다.

반응형

댓글