[SSO] CAS 인증서버 (5) - JDBC인증 등록과정
이전 글에서는 JDBC 인증을 어떻게 사용해서 로그인 하는지에 대해 알아보았다.
이번 글에서는 JDBC 인증이 어떻게 설정이 되었는지에 대해 알아보도록 하자.
가장 먼저, JDBC를 이용해서 사용자 인증을 하기 위해서는 첫 번째 글에서 언급했던 cas-server-support-jdbc 의존성 추가를 해야 한다.
<dependency>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-support-jdbc</artifactId>
<version>${cas.version}</version>
</dependency>
의존성이 추가되면 cas-server-support-jdbc 프로젝트에 있는 spring.factories 파일의 EnableAutoConfiguration에 추가 된 @Configuration 클래스들이 Configuration 객체로 추가 된다.
아래 이미지는 추가 된 CasJdbcAuthenticationConfiguration 클래스이다.
CasJdbcAuthenticationConfiguration 를 살펴보자.
AuthenticationEventExecutionPlanConfigurer 를 구현한 JdbcAuthenticationEventExecutionPlanConfiguration 클래스가 @Configuration 으로 등록되어 있다.
따라서 JdbcAuthenticationEventExecutionPlanConfiguration 역시 @Configuration 객체로 등록이 된다.
그리고 노란색 상자를 자세히 확인해보자.
jdbcAuthenticationHandlers 메소드 내부를 보면 AuthenticationHandler Collection 객체를 생성하고
application.properties 에 설정한 cas 설정의 값을 가져와서 위에서 생성한 AuthenticationHandler Collection에 추가하고 나서 반환하는 메소드 이다.
casProperties.getAuthn().getJdbc() 이 부분은 아래 이미지의 빨간색 박스에 있는 값이다.
따라서 지역변수 jdbc(JdbcAuthenticationProperties)는 getBind, getEncode, getQuery, getSearch 메소드들을 통해 application.properties에 설정한 값을 가져올 수 있게 된다.
예제에서는 cas.authn.jdbc 만 설정했기 때문에 아래 코드만 확인 하면 된다.
jdbc.getQuery().forEach(b -> handlers.add(queryDatabaseAuthenticationHandler(b)));
jdbc.getQuery().foreach 이 부분을 보면 query 배열을 반복하면서 queryDatabaseAuthenticationHandler 메소드에 query 객체를 하나씩 전달해서 handler에 추가(add) 하고 있는것을 확인할 수 있다.
queryAndEncodeDatabaseAuthenticationHandler 를 확인해보자.
빨간색 박스로 표시한 부분이 핵심이다.
간단하게 말해서 queryAndEncodeDatabaseAuthenticationHandler 메소드는 Query를 이용해서 Database에 있는 계정 정보를 조회해서 인증을 처리하는 Handler를 만들어서 리턴하는 메소드 이다.
이때 전달받은 파라미터 b(JdbcAuthenticationProperties.Query) 에 있는 정보들을 handler를 생성하고 설정할 때 사용하는데 우리가 application.properties 파일에 설정했던 값들임을 확인할 수 있다.
QueryDatabaseAuthenticationHandler 내부에 대해서는 이후에 인증과정에서 자세하게 확인해보자.
지금은 어떻게 등록이 되었는지를 확인하는데 집중하도록 하자.
여기까지가 어떻게 JDBC 인증이 설정되는지에 대한 설명이기 때문에 이정도만 이해해도 진행하는데 큰 무리가 없을 것이다.
하지만 조금 더 알고 싶은 사람들을 위해 조금 더 설명하도록 하겠다.
JdbcAuthenticationEventExecutionPlanConfiguration 이 클래스는 어디서 사용하는 것일까??
위 이미지를 보면 JdbcAuthenticationEventExecutionPlanConfiguration 클래스는
AuthenticationEventExecutionPlanConfigurer 인터페이스를 구현한 것을 확인할 수 있다.
그리고 AuthenticationEventExecutionPlanConfigurer 인터페이스를 구현한 구현체들을 확인해면 다음과 같다.
그리고 이 구현체들을 사용하는 곳은 바로 CasCoreAuthenticationConfiguration 클래스이다.
빨간색 박스를 보면 List<AuthenticationEventExecutionPlanConfigurer> 를 파라미터로 받고 있는 것을 확인할 수 있고, @Autowired 애노테이션이 추가되었기 때문에 의존성 주입이 되어 있다는 것을 알 수 있다.
정말로 위에 설명했던 구현체들이 맞는지 Debug 모드로 실행하여 확인해보자.
Debug 모드로 실행 중에 breakpoint를 걸어두고 확인해보았다.
아래 이미지와 같은색 박스끼리 일치한다는 것을 알 수 있다.
List<AuthenticationEventExecutionPlanConfigurer> 자체를 Bean 으로 등록한 것은 아니고, 각각의 구현체를 Bean 으로 등록한 뒤에 List 형태로 주입한 것이다.
프로젝트에서 AuthenticationEventExecutionPlanConfigurer 인터페이스를 구현한 @Configuration 클래스를 생성하고 나서 spring.factories 에 추가하게 되면 해당 클래스 역시 List<AuthenticationEventExecutionPlanConfigurer> 에 포함되는 것을 확인할 수 있다.
이제 authenticationEventExecutionPlan 메소드를 자세히 살펴보자.
핵심은 DefaultAuthenticationEventExecutionPlan 클래스를 Bean으로 추가하는 메소드이다.
그리고 위에서 설명한 AuthenticationEventExecutionPlanConfigurer 인터페이스의 구현체들을 주입 받아서 각각의 구현체들을 DefaultAuthenticationEventExecutionPlan Bean 객체에 설정해주는 작업을 한다.
각각의 AuthenticationEventExecutionPlanConfigurer 구현체들은 DefaultAuthenticationEventExecutionPlan Bean 객체에 어떤 설정을 하는지 configureAuthenticationExecutionPlan 인터페이스의
configureAuthenticationExecutionPlan 메소드를 확인해보자.
쉬운 설명을 위해서 위에서 설명했던 JdbcAuthenticationEventExecutionPlanConfiguration 클래스를 확인해보자.
위 이미지를 보면 어디서 많이 봤을 것이다. 바로 현재 글 위에서 설명했던 내용과 같다.
위에서는 jdbcAuthenticationHandlers() 에 대해서 설명을 했다.
지금은 노란색 박스를 설명하려고 한다.
jdbcAuthenticationHandlers().forEach(h -> plan.registerAuthenticationHandlerWithPrincipalResolver(h, personDirectoryPrincipalResolver));
위에서 설명했던 것처럼 jdbcAuthenticationHandlers() 를 통해 설정된 jdbc 인증처리 handler를 가져온다.
그 다음 파라미터로 받은 DefaultAuthenticationEventExecutionPlan 클래스 인스턴스에 handler와 PrincipalResolver를 등록해준다.
그리고 DefaultAuthenticationEventExecutionPlan 클래스를 확인해보자.
노란색 박스 부분을 보면 JdbcAuthenticationEventExecutionPlanConfiguration 에서 호출한 메소드 임을 확인할 수 있다.
그리고 빨간색 부분을 보면 authenticationHandlerPrincipalResolverMap 라는 멤버변수에 handler를 key로 principal을 value로 put 하는 것을 확인할 수 있다.
authenticationHandlerPrincipalResolverMap 변수는 인증처리를 할 때 사용된다.
사용되는 구체적인 코드는 인증 처리 과정에서 자세하게 설명하도록 하겠다.
지금까지 JDBC 인증방식 설정에 대해 알아 보았다.
다음 글에서는 Client Application을 생성하고 CAS 인증서버와 SSO 테스트를 해보겠다.
마지막으로 CasCoreAuthenticationConfiguration 에 대해 간략히 설명하고 마치겠다.
CasCoreAuthenticationConfiguration 설정 클래스는 cas-server-core-authentication 의존성이 추가되어 있어햐 하는데, 첫번째 글에서 언급했던 cas-server-support-json-service-registry 의존성을 추가하면 의존성 전이를 통해 프로젝트에 추가가 된다.
의존성 전이 순서는 다음과 같다.
cas-server-support-json-service-registry -> cas-server-core-services -> cas-server-core-authentication
다른 @Configuartion 클래스와 마찬가지로 cas-server-core-authentication 프로젝트에 있는 spring.factories 에 추가가 되어 있기 때문에 설정객체로 추가 된다.