[Spring Security] 스프링 시큐리티로 익명 사용자 관리하기

개요

 스프링 시큐리티를 사용하여 프로젝트를 디벨롭하다 보면, 회원가입이나 로그인시에는 시큐리티 필터를 통과할때 인증,인가 프로세스에서 제외하거나, 아예 시큐리티 필터를 타지 않도록 만들어야 한다. 그런데 사실 이런 경우를 제외하고도 로그인이 필요하지 않은 뷰에 필요한 api를 제작할 때 처럼, 시큐리티 필터에서 별도의 인증을 수행하지 않는 요청을 관리해야 하는 경우가 있다.

 

.authorizeHttpRequests(authorize ->
    authorize
    .requestMatchers("/auth/**").permitAll() // 로그인 필요 X
    .requestMatchers(HttpMethod.GET, "/test/**").permitAll() // anonymousUser 테스트
    .anyRequest().authenticated()
)

 

지금까지는 위와 같이 Spring Security Configuration에서 특정 요청에 대해서는 모든 인증을 허락하는 식으로 진행했는데, 디버깅을 하다보니 Authentication객체에 의도하지 않은 값이 들어가는 것을 확인할 수 있었고, 관련 서칭을 하다보니 스프링 시큐리티에서 제공하는 '익명 사용자'에 대해 알게 되었다.

 

 

익명 사용자

 

 시큐리티 필터 체인에서 '익명 사용자'란 로그인을 하지 않은 상태의 사용자를 말하는데, 이렇게 로그인하지 않은 상태의 사용자도 별도의 인증정보를 가질 수 있다. 

 

스프링 시큐리티 내부 코드를 보면 전반적으로

if(SecurityContextHolder.getContext().getAuthentication() == null){
    ...
}

 

과 같은 코드가 여러 군데 나오는데, User객체가 아니라, Authentication객체의 존재 여부로 인증여부를 판단하는 경우가 많다는 것을 알 수 있다.

 

Authentication이 없는 경우에 AnonymousAuthenticationFilter라는 필터가 "anonymousUser"라는 문자열을 principal로 가지는 Authentication객체를 만들어준다. 

 

 

 익명 사용자로 로그인한 경우의 authentication객체의 상태 예시이다. 내가 만든 커스텀 필터에서는 authentication객체가 null이었는데, 시큐리티 필터 체인을 거친 후 ArgumentResolver에서 SecurityContext의 ContextHolder내의 인증객체에 대해서 디버깅을 찍어보니 "anonymousUser"라는 문자열을 principal로 가지고, "ROLE_ANONYMOUS"라는 role을 authority로 가지는 것을 확인할 수 있었다.

 

 다만 authenticated 속성이 true인 것은 이해가 잘 가지 않았는데, 인증되지 않은 객체이므로 authenticated 속성은 false가 되는 것이 맞는 것이 아닐까라는 생각이 들었기 때문이다. 

내가 별도로 설정을 변경한 부분은 없기 때문에, 스프링 시큐리티가 익명 사용자라도 ROLE_ANONYMOUS라는 authority를 가지는 하나의 인증된 사용자로 보는 것일 것이라는 추측을 할 수 있었다.