안녕하세요. 이번 시간에는 스프링 시큐리티에서 자주 보게 될 antPathMatcher에 대해 간단하게 알아봅시다. 이 글에서 반영된 내역들은 모두 다 제 깃 레포에 올라가 있습니다.

 


 프로젝트 구조는 위와 같습니다. 여기서 바꿔야 할 부분을 천천히 보도록 하겠습니다. 먼저, 인증 방식을 프로퍼티에서 설정하지 않겠습니다. 대신에, securityConfig 클래스에서 configureGlobal 메서드로 설정하도록 하겠습니다. 그러니, application.properties의 내용을 아래와 같이 바꾸겠습니다.

 

 인증 정보를 모두 삭제한 모습입니다.

 

 

 다음에 컨트롤러에 GET /user를 받는 것을 하나 추가하겠습니다. 이 링크로는 모든 유저가 접근할 수 있도록 하겠습니다. 이것은 초기화 함수인 configure를 오버라이딩 할 때, antMatchers와 permitAll 등으로 설정할 수 있어요.

 

 

 securityConfig 클래스에서, configureGlobal 메서드를 추가하였습니다. 인 메모리 인증 방식을 쓸 겁니다. 19번째 줄과 23번째 줄에 걸려있는 것들은 인증 정보를 추가하는 것입니다. 하나는 "user"라는 id, 다른 하나는 "admin"이라는 id를 추가합니다. 이들은 각각 "USER"와 "ADMIN" 이라는 role을 가지게 됩니다.

 

 

 다음에 configure를 오버라이드 한 부분에서는, /test 아래에 있는 api는 인증을 해야 접속할 수 있게, /user 아래에 있는 api는 인증을 안 해도 접속할 수 있게 하였습니다. 여기에 사용된 패턴이 /test/**와 /user/**입니다. 실행 결과는 나중에 보도록 하고요. ant 패턴을 test 할 수 있는 api 서버를 하나 만든 다음에 테스트를 진행하였습니다.

 


 먼저 **는 0 혹은 그 이상의 directory path와 matching이 됩니다. 예를 들어, **/1.txt는 아래와 같이 매칭이 됩니다.

 

 먼저 **/1.txt입니다. **가 0개 혹은 그 이상이라 했으니, 1.txt도 당연하게 매칭이 됩니다.

 

 

 123/456/789/1.txt는 어떨까요? 이것도 참이 됩니다. 왜냐하면, 123/456/789는 0개 이상의 디렉토리를 거쳐갔기 때문입니다.

 

 

 이건 false가 됩니다. 왜냐하면 경로 /를 기준으로 0개 이상이기 때문입니다. 1.txt는 /가 들어가지 않았으니 false가 찍힐 겁니다.

 


 *과 ?는 캐릭터를 기준으로 작동합니다. *는 0개 이상의 character, ?는 하나의 캐릭터와 대응됩니다. 예를 들어보겠습니다.

 

 일단 /com/**/ 이 부분은 /com의 하위 디렉토리를 의미합니다. /com/abcde.txt는 /com의 하위 디렉토리에 있습니다. 그러면 텍스트 파일인 abcde.txt가 *.txt에 걸리냐가 문제인데요. abcde는 0자 이상의 캐릭터입니다. 따라서, true입니다.

 

 

 반면에 /com/**/?.txt는 이야기가 달라집니다. abcde.txt는 /com의 하위 디렉토리에 있는 것은 맞습니다. 그런데, abcde는 1글자가 아니라 5글자이므로 ?에 match가 되지 않습니다. 따라서, false가 됩니다.

 

 

 이건 어떨까요? 천천히 해석해 보면, com 하위 폴더의 abc 하위 폴더 밑에 있는 무언가를 패턴으로 잡고 있음을 볼 수 있어요. target을 보면, com/a/a/a/b/c가 있는데요. 저건 pattern과 매치되지 않아요. 왜? com은 있는데 com 밑에 abc라는 것은 아무리 찾아봐도 없네요.

 

 그런데, 이것은 true가 떨어집니다. com 밑에 abc가 있는 패턴이기 때문이에요.

 

 

 저 경우는 왜 true가 나올까요? *는 0개 이상의 문자를 의미합니다. gh 앞에 cho가 왔고 gh 뒤에 아무것도 없네요. 패턴에 매칭됨을 매우 쉽게 알 수 있어요.

 

 

 그런데 chogh/는 *gh* 패턴에 걸리지 않아요. 앞에는 문제가 없어요. cho는 0개 이상의 문자이기 때문입니다. 뒤에가 문제입니다. /는 경로를 가리키므로 걸리지 않아요. 여기까지 보셨으면 대략적으로 어떤 식으로 match가 일어나는지 눈치 채셨으리라 생각합니다. 조금 더 정리를 하고 싶으시다면, 이 문서를 참고하시는 게 좋겠습니다. 다시 코드로 돌아와 보겠습니다.

 


 config 부분에서 인증 설정 부분만 보겠습니다.

 

 

 /test/**는 뭔가요? /test 밑에 있는 모든 요청이라는 의미입니다. /testa 이런 것과는 당연히 매치되지 않을 겁니다. 다음에, /user/**에 대해서는 permitAll을 걸었는데요. 이는 /user 밑에 있는 요청들은 모두 허용한다는 의미입니다. postman으로 날려보겠습니다.

 

 

 Authorization 표시가 빠졌어요. 이는 인증에 필요한 정보를 넘기지 않는다는 의미입니다. 보니까 정상적으로 userGet이 리턴되었는데요. 이는 제가 /user 밑에 있는 요청들은 모두 permit 처리했기 때문입니다.

 

 

 그런데, GET /test를 호출했더니, 401이 떨어졌습니다. 이는, /test 하위에 있는 것들은 모두 인증을 해야 들어갈 수 있게 걸어놓았기 때문입니다.

 

 

 userRole을 가진 user로 인증 정보를 채우고 다시 api를 불러보면, 정상적으로 동작함을 알 수 있습니다.