Whiteship's Note


Acegi로 웹 애플리케이션 보안하기 3



3. 인증하자.(보안된 정보에 접근할 때 로그인을 하도록...)

이제부터 이전 글에서 등록한 FilterChainPorxy에 필터를 하나씩 등록하면 됩니다. 그러려면 일단 필터를 bean으로 등록해야겠죠. 그리고 그 필터가 종속성을 가지는 객체들도 역시 bean으로 등록하면 됩니다.

인증을 하기 위해 Acegi에서 제공하고 있는 필터는 AuthenticationProcessingFilter입니다.
사용자 삽입 이미지
이 필터는 authenticationManager를 사용하여 인증 처리를 하고 있습니다. 동작하는 원리는 IBM에 올라온 기사를 참조하면 자세히 설명되어 있습니다.
사용자 삽입 이미지
간략히 설명을 하면, APF로 요청, 응답, 필터 체인 객체가 넘어옵니다.(1) 그 뒤에 APF에서 인증 토큰(username, password, 등 기타 요청 개체에 딸려온 정보)을 만들고(2), 이 것을 AuthenticationManager에 넘겨줍니다.(3)

그럼 이제, AuthenticationManager를 등록해야겠습니다.
사용자 삽입 이미지
authenticationManager에서는 하나 이상의 authenticationProvider를 사용하여, 인증 작업을 처리하고 있습니다. manager는 여러 provider를 사용하여 어떤 provider가 APF로 부터 받은 인증 토큰을 지원하는지 확인합니다.(4) 그러려면 인증 토큰을 provider에게 보내야겠죠.(5)

authentication Provider는 manager로 부터 받은 인증 토큰에서 username을 꺼낸 다음, userChache가 등록되어 있다면 이 정보를 user cache service라는 녀석에게 넘깁니다.(6) 하지만 위의 예제는 아직 userChache를 사용하고 있지 않기 때문에, (7), (8)에 대한 설명은 생략하겠습니다.

userChache가 없거나, userChache에서 username으로 확인(9) 결과가 null 이면, 다시 username을 이번에는 user detail service에게 넘깁니다. (10)userDetailService는 뒷단(위의 예제에서는 프로퍼티 파일을 사용했네요.)에서 사용자 정보를 찾습니다.(11) 해당 username에 대한 사용자 정보를 찾아서 가져오거나, 그런 사용자가 없다는 예외를 발생시킬 것 입니다.(12)

이렇게해서 찾은 정보와 인증 토큰의 정보를 가지고 비번 확인을 합니다. 일치하면, 해당 사용자 정보를 다시 Authentication Manager에게 넘겨주고, 일치하지 않으면 예외를 발생시킵니다.(13) Authentication Manager는 다시 이 정보를 APF에게 잔달합니다.(14) 그러면 APF는 이 정보를 Security Context에 저장하고(15) 다음 필터를 호출합니다.(16)

자 이제 거의 다 끝났습니다.

마지막으로 할 일은 APF를 "Acegi로 웹 애플리케이션 보안하기 2"에서 만들었던 FilterChainProxy에 등록하는 일입니다.
사용자 삽입 이미지
filterChainProxy의 filterInvocationDefinitionSource 속성에 위와 같이 설정해 줍니다. 모든 URL은 비교하기 전에 모두 소문자로 바꾸고, ANT 스타일의 표현식을 사용할 것이라는 설정과, 모든 url이 authenticationProcessingFilter를 거치도록 설정했습니다.

http://www.acegisecurity.org/acegi-security/apidocs/constant-values.html#org.acegisecurity.util.FilterChainProxy.TOKEN_NONE

위 링크에서 Acegi에서 사용할 수 있는 상수들을 참조할 수 있습니다.

자 이렇게 하면...
이제 인증(로그인)은 제대로 동작하지만, 여전히 인증을 하지 않고도 보안이 필요한 자원에 누구나(로그인을 하든 안하든 관계없이)접근할 수 있습니다.

top


Authentication Manager



사용자 삽입 이미지
Spring Security를 구성하는 다섯 가지 컴포넌트 중에 하나인 Authentication Manager는 인증을 담당하고 있습니다.

Authentication Manager는 인증을 시도(authenticate 메소드 호출)해서 성공하면, Authentication 객체를 반환하고, 실패하면, AuthenticationException 예외를 던지는 메소드를 가지고 있습니다.

이 인터페이스의 구현체로 Provider Manager를 제공하고 있으며, 이 클래스를 여러 인증 방식을 사용할 수 있는 관리자 역할을 하고 있습니다. Spring Security에서 제공하고 있는 인증 방식은 총 14가지 입니다. 그 중에서 가장 자주 사용할 것 같은 Provider는 DAO를 사용하여 인증 정보를 가져오는 DaoAuthenticationProvider입니다.

사용자 삽입 이미지
하늘색 선은 implements, 파란색 선은 extends, 빨간 선은 composition 입니다.
하늘색 네모는 인터페이스, 파란색 네모는 클래스입니다.

DaoAuthenticationProvider는 UserDetailsService 인터페이스를 통해서 사용자 정보(UserDetail)를 가져옵니다.

UserDetailsService 인터페이스를 직접 구현하여 설정해도 되지만, Spring Sercurity에서 제공하는 InMemoryDaoImpl 또는 JdbcDaoImpl을 사용할 수도 있습니다. DB에서 사용자 정보를 가져오려면, JdbcDaoImpl을 사용하는 것이 좋겠습니다.

JdbcDaoImpl에는 dataSource, usersByUsernameQuery, authoritiesByUsernameQuery 속성을 설정하여 DB로 부터 사용자 정보를 가져옵니다. usersByUsernameQuery에는 username, password, enabled를 SELECT하고, authoritiesByUsernameQuery에는 username과 authority를 SELECT 하는 쿼리를 설정해 줍니다.

사용자 삽입 이미지

좀 복잡해 보이지만, 철저하게 인터페이스 기반으로 작성되어 있으며, 역할을 분담해 놓은 모습이 매우 깔끔합니다.

bean 설정을 다음과 같이 할 수 있습니다.
사용자 삽입 이미지
설정 내용은 상당하지만, 자세히 살펴보시면 클레스 상속 구조와 일치하기 때문에, 쉽게 이해하실 수 있습니다.
사용자 삽입 이미지
특히 DaoAuthenticationProvider에는 passwordEncoder(비번 암호화)와 saltSource, userCache(사용자 정보 캐쉬 사용) 들을 설정할 수도 있습니다.

마지막으로 정리하자면, AuthenticationManager의 구현체로 ProviderManager가 있으며, 이 녀석은 여러 AuthenticationProvider를 사용할 수 있습니다.
그 중에서도 DaoAuthenticationProvider는 UserDetails를 사용하여 사용자 정보를 가져옵니다.
이 때 JdbcDaoImp 이라는 구현체를 사용하여 datasource를 사용하여 사용자 정보와 권한을 가져오는 SQL 쿼리를 설정해주면 끝.

참조 : Spring In Action 2nd
top