인프런 커뮤니티 질문&답변

Truestar님의 프로필 이미지
Truestar

작성한 질문수

스프링 시큐리티

5) 웹 기반 인가처리 DB 연동 - FilterInvocationSecurityMetadataSource (2)

서버 기동 후 루트 접근 시 `/` AccessDeniedException 질문입니다

작성

·

535

0

예제에서는 DB 리소스 설정 이후에도
루트접근이 가능해 보이는데, 저의경우는 접근이 불가능합니다

아래 이미지는 서버 기동 직후, 브라우저를 통해 루트 접근시
차단이 되는 부분에 BreakPoint 를 잡아 캡쳐했습니다.

익명 사용자의 경우에 허용되어야 할 `/` 웹 루트 경로가
Denied 되는 것은 어느 부분이 문제일까요..

DB 연동은 잘 처리가 되었으나 이부분에서 막힙니다.
특별히 설정을 바꾼것이 없는데
DB 연동 처리 이후, 계속 여기서 부터 막힙니다.
어느 부분부터 살펴봐야 해결이 될까요..?

혹시 정상인가요?
( 지난 강의 돌려보다가 문뜩 생각이 듭니다)

혹제 제가 놓친부분에 대해 조언을 구합니다.
읽어주셔서 감사드립니다.

답변 5

1

정수원님의 프로필 이미지
정수원
지식공유자

아 네 축하드립니다^^

덕분에 저도 좋은 해결책을 알게 된 것 같습니다

끝까지 문제해결을 위한 도전에 박수를 보내드립니다~

1

정수원님의 프로필 이미지
정수원
지식공유자

네 소스는 잘 검토해 보았습니다.

원인은 다음과 같습니다. 다만 정확한 해결책은 조금 더 살펴 보아야 할 것 같습니다.

아래 를 보시면 현재 필터 리스트 중에서 맨 마지막에 위치하는 권한 필터가 customFilterSecurityInterceptor() 로 적용되지 않고 있습니다.

즉 

@EventListener(ContextRefreshedEvent.class)
@Transactional
public void onContextRefreshedEvent() throws Exception {
getHttp()
.addFilterBefore(customFilterSecurityInterceptor(), FilterSecurityInterceptor.class);

}

위 구문이 시큐리티 초기화 시 필터를 구성할 때 포함되지 않는 것 같습니다

예상컨대 

@Override
protected void configure(final HttpSecurity http) throws Exception {

http.addFilterBefore(customFilterSecurityInterceptor(), FilterSecurityInterceptor.class)

}

위 구문 안에서 처리해야 필터가 정상적으로 등록되는 것 같습니다.

아래에 보시면 FilterSecurityInterceptor 가 12번째와 13번째에 있습니다.

12번째가 직접 구현한 구현체입니다.

그렇기 때문에 아래에 보시면 FilterSecurityInterceptor 클래스인데요
SecurityMetadataSource 구현체가 UrlFilterInvocationSecurityMetadataSource 가 아닌 ExpressionBasedFilterInvocationSecurityMetadataSource 로 되어 있고 권한 설정이 any request / authenticated 라고 되어 있기 때문에 즉, 어떠한 요청에도 인증을 받아야만 모든 리소스에 접근이 가능하도록 설정이 되어 있습니다. 시큐리티의 기본설정입니다

구성은 잘 하신 것 같은데 필터를 적용하는 순서 혹은 시점이 문제가 되는 것 같습니다.

이 부분은 좀 더 디버거를 상세하게 보셔야 할 것 같습니다.

저도 정확한 원인이 무엇인지 조금 더 살펴 보도록 하겠습니다.

Truestar님의 프로필 이미지
Truestar
질문자

그렇군요.. 저도 다시 살펴보겠습니다!!

Truestar님의 프로필 이미지
Truestar
질문자

맞습니다. 그 부분 protected void configure(final HttpSecurity http) 내에서
MetadataSource 등록을 하게되면

루트 `/` 접근이 막히는건 해제가 되지만, Url 인가 적용이 불가능하게 되버려서 
이 상황에 시도해 본것이, DB 데이터 초기화가 끝나고 처리 하려다 보니
@이벤트리스너 에서 초기화 코드를 넣게 되었네요..

제가 경험이 없다보니 이것 말고는 떠오르는게 없더라구요.. 혹시 방도가 있을까요?

한가지 시도할 방법이 또 있다면,

  • 초기화때 DB 에서 가져오지 못한 리소스(URL ) 를 다시 로딩
    : UrlFilterInvocationSecurityMetadataSource 에서 
    reload() 메서드 구현을 시도했었습니다

1

Truestar님의 프로필 이미지
Truestar
질문자

강사님. 깃헙 공유했습니다
관련 프로젝트 모듈은 `2-core-spring-security` 입니다

그리고, 이번 문제는 아래 질문과도 연계가 됩니다.
여기에 두번째로 남긴 질문에서도 정보를 얻으실 수 있어요.
Custom `FilterSecurityInterceptor` 초기화 시점 변경에 대한 질문입니다

보시기 전에 참고하셔야 되는 부분은

      • DB 는 H2 TCP 서버 ( 메모리기반 ) 입니다
        : DB를 따로 설치하지 않기위해 설정을 해야 했습니다
        : config.DummyDataLoader 에 의해 Resource 가 초기화 됩니다

      • SecurityConfig 에서 커스텀 Bean 등록되는 부분의 @Bean 어노테이션을 주석처리 했습니다
        : 이유 는, 아래 @Bean 등록 전에 DB에 Resource 데이터 입력이 되어야 하는데
        @Bean 초기화 이후, DB로 데이터 입력이 되기 때문에
        아래 Bean 들은 DB에 없는 URL 인가정보를 를 불러들이기 때문입니다.(resourceMap size = 0)
        //  @Bean //> ContextRefreshedEvent 이벤트 발생 이후에 호출되기 위해 Bean 등록 지양
        public FilterSecurityInterceptor customFilterSecurityInterceptor() throws Exception {
        }

        // @Bean //> ContextRefreshedEvent 이벤트 발생 이후에 호출되기 위해 Bean 등록 지양
        public FilterInvocationSecurityMetadataSource urlFilterInvocationSecurityMetadataSource() throws Exception {
        }

살펴봐 주셔서 감사드립니다.

1

정수원님의 프로필 이미지
정수원
지식공유자

DB 와 연동해서 인가 처리를 구현했다면 리소스권한 테이블에 URL 정보와 권한정보가 설정되어 있는 정보만 인가처리 대상이 됩니다.

만약 루트(/) 정보와 권한정보를 별도로 테이블에 입력하지 않았다면 인가 처리 대상이 되지 않으므로 모든 사용자가 접근할 수 있게 됩니다.

캡처 이미지에서 접근거부예외로 떨어지는 것을 보면 분명 해당 URL 의 리소스에 인가설정이 되어 있다는 것인데 만약 그런설정을 하지 않았는데 위의 결과가 나타난 것이면 다른 이유가 있을 것 같습니다.

혹 github 소스 공유가 가능할까요?

0

Truestar님의 프로필 이미지
Truestar
질문자

강사님. 해결되었습니다.

  1. MetadataSource 에서 reload 메서드 로 DB 데이터 로딩 기능 구현 후,
  2. SecurityConfig.java 에서 @ApplicationReadyEvent 리스너 에서
  3. event.getApplicationContext() .getBean() 으로 UrlFilter...MetadataSource 가져온 후
  4. .reload() 를 실행

이런 과정으로, 
java/resources/data.sql  과 DummyDataLoader 의 데이터 삽입 과정이 끝나고,
ApplicationReadyEvent 시점에 UrlFilter...MetadataSource 에서
리소스 리로딩 해주는 방식으로 해결을 봤습니다.

Bean 을 등록하는 부분 변경이나, DataSource 의 데이터 입력 시점을 변경하는 방법은
아무리 찾아도 방법이 없는것으로 보아, 제가 어려운 방법을 택한게 아닌가 싶습니다.

문제 해결을 위해 답글 남겨주셔서 많은 도움이 되었습니다.

정말 감사드립니다.

Truestar님의 프로필 이미지
Truestar

작성한 질문수

질문하기