Log4j로 검색한 결과 :: 시소커뮤니티[SSISO Community]
 
SSISO 카페 SSISO Source SSISO 구직 SSISO 쇼핑몰 SSISO 맛집
추천검색어 : JUnit   Log4j   ajax   spring   struts   struts-config.xml   Synchronized   책정보   Ajax 마스터하기   우측부분

회원가입 I 비밀번호 찾기


SSISO Community검색
SSISO Community메뉴
[카페목록보기]
[블로그등록하기]  
[블로그리스트]  
SSISO Community카페
블로그 카테고리
정치 경제
문화 칼럼
비디오게임 스포츠
핫이슈 TV
포토 온라인게임
PC게임 에뮬게임
라이프 사람들
유머 만화애니
방송 1
1 1
1 1
1 1
1 1
1

Log4j로 검색한 결과
등록일:2008-03-16 15:50:41
작성자:
제목:[프레임워크 전략 ④] 자바 프레임워크 활용 전략


자바의 장점은 JCP, 프레임워크, 오픈소스이다. JCP를 통해서 호환성과 성능, 안정성이 보장된 스펙을 만들고, 잘 설계된 스펙들은 상호 연관성을 갖고 구조화된 구조로 확장한다. 이러한 결과물이 프레임워크이고 프레임워크를 지원하는 핵심은 오픈소스와 벤더이다. 이렇듯 프레임워크는 자바 구현체의 핵심이기도 하다. 특집 4부에서는 수 없이 많은 자바 프레임워크 중에서 데이터베이스와 보안 기능 구현에 효과적으로 사용할 수 있는 iBatis와 Acegi Security의 활용 방법들에 대해 알아본다.

웹 애플리케이션을 개발하면서 가장 중요하면서도 복잡한 기능 둘을 꼽으라면 단연 데이터베이스와 보안 기능일 것이다. 특집 4부에서는 데이터베이스 기능을 효과적으로 구축할 수 있는 iBatis와 보안 기능 구현용 프레임워크인 Acegi Security에 대해 알아볼 것이다.

데이터베이스를 사용하는 자바 애플리케이션을 개발하려면 JDBC 코딩이 필수적이다. JDBC 코딩을 할 때에는 데이터베이스 커넥션 자원을 코드 상에서 관리해야 한다. 또 개발 코드에 SQL 문도 포함된다.

데이터베이스 커넥션 자원을 관리하는 것도 문제지만 개발 과정에서 상당수의 비즈니스 로직이 SQL 문에 포함되고, 다시 이런 SQL 문이 코드에 포함되어 SQL 문을 관리하는 것이 상당히 복잡해지게 마련이다. iBatis는 데이터베이스 자원 관리를 완벽하게 추상화하고, SQL 문을 코드에서 분리하여 XML로 관리할 수 있도록 해 주는 오픈 소스 프로젝트이다.

Acegi Security는 애플리케이션 개발 과정에서 가장 민감하면서도 복잡한 보안 기능을 보다 안정적이고 쉽게 구연할 수 있도록 도와주는 프레임워크이다. 보안 개념을 사전에 고려하여 아키텍처를 정의하는 것은 어려운 일이다. 그렇다고 보안 기능을 무작정 추가하여 개발하다 보면 비즈니스 로직이 보안 코드 탓에 엉망이 되는 경우가 비일비재하다.

Acegi Security는 이런 문제를 보다 효과적으로 해결할 수 있는 방법들을 제공한다. 또, 요즘 인기를 끌고 있는 AOP(Aspect Orient Programming) 개념을 도입하여 기존 코드에 영향을 미치지 않으면서도 다양한 보안 패턴을 적용 시킬 수 있는 스프링 기반 프레임워크이다.

  SQL 맵퍼 iBatis SQLMap

iBatis는 www.ibatis.org에서 진행 중인 오픈 소스 프로젝트이다. iBatis의 기능을 한 마디로 요약하자면 SQL 맵퍼라고 말할 수 있다. iBatis를 사용하면 개발 코드에서 SQL문을 분리하여 재사용성을 높일 수 있다. 또, 반복적인 JDBC 코드도 줄일 수 있다. 일반적으로 데이터베이스와 연동하는 자바 애플리케이션을 개발하기 위해서는 JDBC 코딩을 한다.

JDBC 코딩은 다음과 같이 6단계의 절차로 이루어지는데, 이 중에서 1번과 2번은 커넥션 풀을 사용하거나 공통 모듈로 추상화 시켜놓는 것이 일반적이다. 개발 과정에서 빈번하게 접하는 것은 3번부터 6번까지의 절차이다. 이중에서도 3번을 수행하려면 스트링 객체로 SQL문을 만들어야 한다.

더불어 메모리의 효과적인 활용을 위해 StringBuffer를 사용하여 SQL문을 만들어 나가는 과정에서 여러 조건에 해당하는 if문 로직도 포함되게 된다.

문제는 이처럼 코드와 SQL문을 결합하여 사용할 경우 중복된 SQL문이 여러 클래스에 혼재하게 되어 SQL문의 재 사용성과 가독성이 떨어진다는데 있다. 4번에서 SQL문을 실행한 후 결과 값인 ResultSet으로부터 데이터를 추출하고 객체에 저장하는 코드를 5번 절차에서 수행하고 6번에서 자원을 close하는 절차를 통해서 JDBC 코드가 개발된다.

이때, 5번 절차에서 데이터를 추출하고 자바 빈에 값을 세팅하는 코드를 매번 추가해야 하고 6번 절차에서 예외사항이 발생할 경우, 예외처리를 잘못하면 메모리 누수가 발생하기 쉬운 구간이다.

JDBC 개발 절차  


1. Driver : JDBC Driver를 등록한다.
2. Connection : 데이터베이스에 연결한다.
3. Statement : query문 수행객체를 생성한다.
4. Execute : query문을 실행한다.
5. Result : query 실행 결과를 받는다.
6. Close : Connection, Statement를 닫는다.




iBatis는 6단계의 JDBC 개발 전체를 추상화하여 개발 생산성을 높이고 있다. iBatis를 이용하면 SqlMapConfig.xml에 데이터베이스 정보를 등록하고 이 정보를 이용하여 데이터베이스 커넥션을 생성할 수 있다. SqlMapConfig.xml 파일과 지원 라이브러리를 통해서 JDBC 개발 절차의 1번과 2번, 6번을 추상화 하고 있다.

iBatis는 또한 SqlMap이라는 xml 파일을 관리한다. SqlMap xml 파일은 SQL 정보, 특정 SQL 문과 입력된 데이터를 어떻게 결합할 것인가, SQL의 실행 후 어떤 자바 빈에 데이터를 저장할 것인가와 관련된 정보를 관리한다. 따라서 iBatis는 SqlMap xml 파일과 3번, 5번 절차를 추상화한다. 마지막으로 4번 SQL문을 실행하는 다양한 라이브러리를 제공한다.

이와 같이 iBatis를 사용하면 SqlMap xml 파일을 사용하여 SQL문을 중앙 집중적으로 관리할 수 있다. 또, SQL문과 결합되는 입력 값과 SQL문의 결과를 담는 자바 빈을 일괄적으로 관리하여 SQL문의 재사용성도 높일 수 있다. 더불어 SQL문과 입력 값을 설정하는 코드 및 ResultSet으로부터 데이터를 추출하는 반복적인 코드를 줄이는 효과도 얻을 수 있다. 또한 Connection, PrepareStatement, ResultSet 객체를 프레임워크 내부에 숨겨 놓아 개발과정에서 이들 객체에 접근할 수 없다. 때문에 개발과정에서 자원 해제와 관련된 부분을 신경 쓸 필요가 없어진다.

iBatis
www.ibatis.org에서는 iBatis를 데이터베이스 코딩을 쉽게 하기 위한 데이터 맵퍼 프레임워크(Data Mapper Framework)라고 소개하고 있다. 자바, 닷넷 그리고 루비 세 가지 버전의 프레임워크를 제공하고 있다.

iBatis 프로젝트는 iBatis SQL Map과 iBatis DAO 컴포넌트로 구성되어 있다. 이 중 iBatis SQL Map은 SQL문 관리에 초점을 맞추고 있다. iBatis DAO 컴포넌트는 하이버네이트(hibernate)와 iBatis SQL Map을 함께 사용할 경우 트랜잭션 통합과 같은 저장 메커니즘에 초점을 맞추고 있다.

현재 iBatis는 안정화 버전으로 2.1.7버전을, 개발버전으로는 2.2.0버전을 베타로 릴리즈한 상태다.

<그림 1>은 iBatis의 작동 방식을 잘 설명하고 있다. iBatis는 데이터베이스 커넥션에 관한 정보와 캐시 사용 여부, 트랜잭션 최대 개수, 최대 세션 개수 등 데이터베이스 커넥션과 관련된 전반적인 정보로 구성된다.

또, SQL 처리를 위해 SQL Map xml 파일들의 위치 정보를 기록하는 SqlMapConfig.xml 파일과 SQL문과 PrepareStatement 파라미터, ResultSet 결과 맵핑 정보를 기록하는 하나 이상의 SqlMap.xml로 구성된다.

PrepareStatement 파라미터로 입력되는 형태는 자바 빈과 맵 객체, 원시 데이터형 변수, XML문의 형태로 만들 수 있다. ResultSet 결과 맵핑은 자바 빈이나 맵 객체, 원시 데이터형, XML의 형태로 만들 수 있다.

SqlMapConfig.xml
<리스트 1>을 보면 SqlMapConfig.xml의 루트 엘리먼트(Root Element)는 ‘sqlMapConfig’이다. ‘sqlMapConfig’는 다섯 개의 자식 엘리먼트(Element 이하 ‘요소’)를 포함할 수 있다.


 <리스트 1> SqlMapConfig.xml 예제



●properties 요소
SqlMapConfig.xml은 ‘${key_name}’ 형태의 변수를 값으로 사용할 수 있다. <리스트 1>의 경우 driver, url, username, password가 ‘${key_name}’ 형태의 변수를 사용한 예이다. 이러한 key_name은 SqlMapClient 인스턴스가 생성될 때 실제 값으로 대치된다. key_name의 실제 값은 ‘keyname=value’의 형태로 properties 파일에 저장된다. sqlMapConfig에서 사용하는 properties 파일은 properties 요소의 resource 속성을 이용하여 등록된다.

●settings 요소
iBatis SqlMap을 사용하기 위해서는 SqlMapClient 인스턴스를 생성해야 한다. setting 요소는 SqlMapClient 인스턴스를 위한 옵션과 최적화를 위한 설정하는 역할을 담당한다. setting 요소는 일곱 개의 속성을 갖고 있고 각 속성의 의미는 <표 1>과 같다.



●typeAlias 요소
typeAlias 요소를 이용하여 긴 클래스 명을 참조하기 위한 짧은 이름을 명시한다. <리스트 1>의 경우 com.imaso.vo.EmpVO와 com.imaso.vo.DeptVO를 각각 emp와 dept로 명시하고 있다. typeAlias에서 설정된 별칭은 sqlMapConfig.xml과 sqlMapConfig에서 등록된 SqlMap.xml에서 사용할 수 있다.

●transactionManager 요소
transactionManager 요소는 트랜잭션과 관련된 설정을 담당한다. transactionManager 요소는 type 속성을 갖고 있다. type에는 클래스 명을 사용하거나 사전에 정의된 별칭을 사용할 수 있다. iBatis SqlMaps는 사전에 세 개의 별칭을 정의하고 있다. 그 별칭의 종류와 의미는 <표 2>와 같다.



transactionManager는 dataSource 요소를 갖는다. dataSource 요소는 type으로 ‘SIMPLE’, ‘DBCP’, ‘JNDI’를 설정할 수 있다. ‘SIMPLE’은 iBatis SimpleDataSource connection 풀을 사용하여 데이터 소스를 제공한다는 설정이고 DBCP는 자카르타 DBCP를 사용한다는 지정이다. ‘JNDI’는 WAS의 JNDI 컨텍스트로부터 DataSource를 가져온다는 의미이다.

●sqlMap 요소
sqlMap 요소는 iBatis Sql Maps에서 사용할 sqlMap xml 파일들을 지정하는 역할을 한다. sqlMap 요소는 한 개 이상 등록해야 하며 sqlMap xml 파일을 지정하는 방식은 클래스 패스와 절대경로를 이용하여 지정할 수 있다. <리스트 1>에서 emp.xml은 resource 속성을 사용하여 클래스 패스로 설정한 것이고, dept.xml은 url 속성을 통하여 절대경로로 설정한 예이다.

SqlMap xml 파일
<리스트 2>는 오라클 디폴트 스카미인 scott의 emp 테이블을 대상으로 조회, 수정, 입력, 삭제를 대상으로 하는 SqlMap xml의 예제이다. SqlMap xml 파일은 sqlMap 엘리먼트를 루트로 한다. <리스트 2>에서 sqlMap은 select, insert, update, delete 요소를 포함하고 있다. 각 요소는 parameterClass 속성을 가지고 있다. 또, 이 속성에 typeAlias로 별칭이 설정된 EmpVO 클래스를 지정하고 있다.

parameterClass로 지정된 클래스는 입력 파라미터를 의미한다. id가 getEMP인 select 요소는 parameterClass로 별칭이 emp인 EmpVO 객체가 설정되어 있다. 입력 파라미터로 EmpVO 인스턴스가 입력되면 id가 getEMP인 SQL문과 결합하게 된다.

이 때 EmpVO 객체의 인스턴스는 empno라는 멤버 변수를 가지고 있으며, getter 메소드와 setter 메소드가 선언되어 있어야 한다. EmpVO가 앞의 조건들을 충족하는 자바빈이라면 EmpVO 인스턴스의 empno 멤버 변수의 값은 #empno#와 결합하여 PrepareStatement 객체를 생성하고 실행된다. 나머지 SQL문 역시 같은 원리로 작동된다.

id가 getEmpList인 select 요소의 SQL문은 CDATA 섹션으로 보호되고 있다. 이것은 SQL문에 ‘<’, ‘>’ 이 포함될 경우 SqlMap xml 문서는 web-formed 하지 않는 상태가 된다. 이런 문제를 해결하기 위해서는 ‘<’, ‘>’문자를 ‘<’, ‘>’로 바꾸거나 CDATA 섹션으로 설정하여 모든 값을 문자로 인식하도록 해야 한다. getEmpList는 CDATA 섹션을 적용한 예이다.


 <리스트 2> SqlMap xml 파일 예제(sqlmap /emp.xml)



다른 요소와 달리 select 요소는 resultClass 속성을 가지고 있는 것이 특징이다. <리스트 2>에서는 emp 별칭을 사용하여 EmpVO를 설정하고 있다. resultClass는 SQL문이 처리된 후 조회데이터를 row 별로 담을 자바 빈 클래스를 지정하는 클래스이다.

resultClass에 지정된 자바 빈의 select절 컬럼명과 동일한 멤버 변수를 포함하고 각 멤버 변수에 대한 getter 메소드와 setter 메소드가 정의된 자바 빈이라는 제약조건을 갖는다.

●ParameterMap과 ResultMap
SqlMap xml 파일에서 입력 파라미터와 결과를 리턴 하는 데이터형을 지정하는 방식으로 parameterClass와 resultClass 속성을 사용하는 방법에 대하여 알아보았다. parameterClass와 resultClass에 지정된 자바 빈의 parameterClass는 #변수명#과 동일한 멤버 변수명을 갖는 자바 빈이어야 한다.

또, resultClass는 select 절의 모든 컬럼명과 일치하는 멤버변수들을 갖는 자바 빈이어야 한다는 제약조건이 있다. 이러한 제약조건을 해결하는 방안으로 ParameterMap과 ResultMap을 지원한다.

<리스트 3>은 <리스트 2>의 getEmpList 요소에 resultMap을 사용하도록 변형한 예제이다. <리스트 3>은 select절의 컬럼명이 모두 대문자로 설정되어 있다. 이 SQL문이 실행될 경우 결과는 로우(Row) 별로 EmpVO 인스턴스에 설정되도록 select 요소의 resultMap 속성으로 empMap을 지정하고 있다.

id가 empMap인 resultMap 요소는 데이터를 저장할 때 사용할 빈(class 속성)과 컬럼별(column 속성) 대상 멤버 변수명(property)을 설정한다. 더불어 전체 8 컬럼 중 다섯 개의 컬럼만을resultMap 요소에 설정하여 다섯 개의 컬럼 데이터만이 EmpVO 인스턴스에 저장되도록 설정하고 있다.


 <리스트 3>resultMap을 적용한 예



Sql Maps API 사용하기
지금까지 SqlMapConfig.xml과 sqlMap.xml을 설정하는 방법을 알아보았다. 이제 이것을 바탕으로 xml 설정을 사용하는 API에 대해 알아볼 차례이다. Sql Maps는 애플리케이션 개발자가 com.ibatis.sqlmap.client.SqlMapClient 인터페이스만을 사용하면 되도는 간략한 구성의 API를 지원한다.

●SqlMapClient 인스턴스 생성
SqlMapClient 인스턴스를 만들기 위해서는 SqlMapClientBuilder 클래스의 static 메소드인 buildSqlMap()메소드를 사용한다. buildSqlMap 메소드에 클래스 패스 상에 존재하는 SqlMapConfig.xml 파일의 Reader 인스턴스를 입력하여 SqlMapClient 인스턴스를 만들 수 있다.


 <리스트 4>SqlMapClient 인스턴스 생성 코드



●SqlMapClient API
SqlMapClient 인스턴스를 생성하면 다음과 같은 메소드를 활용할 수 있다.

SqlMapClient 클래스의 주요 메소드  


* public void startTransaction () throws SQLException
* public void commitTransaction () throws SQLException
* public void endTransaction () throws SQLException
* public Object insert(String id, Object param) throws SQLException
* public int update(String id, Object param) throws SQLException
* public int delete(String id, Object param) throws SQLException
* public Object queryForObject(String id, Object param) throws SQLException
* public List queryForList(String id, Object param) throws SQLException




<리스트 5>는 iBatis Sql Maps를 이용한 트랜잭션 예제코드이다. updateEmpHiredate() 메소드는 SqlMapClient 인스턴스인의 startTransaction() 메소드로 트랜잭션을 시작하고 commitTransaction()로 종료한다. 트랜잭션 처리 중 SQLException이 발생할 경우 endTransaction() 메소드를 호출하여 트랜잭션을 롤백하고 종료하는 로직을 담고 있다.

queryForObject() 메소드에 SQL id와 입력 파라미터 객체 ‘inputEmp’ 객체를 전달하면 [코드 2]의 ‘getEmp’ select 요소와 결합하여 SQL문이 실행되고 결과를 Object 형으로 리턴 한다.

조회 결과인 ‘emp’ 객체의 hiredate를 설정한 뒤에 update 메소드에 ‘updateEmp’인 SQL id와 수정한 데이터를 저장하는 emp 객체를 파라미터로 전달하여 데이터를 수정하는 로직으로 구성되어 있다.

<리스트 5>는 전형적인 iBatis Sql Maps 코딩 방식이다. 데이터베이스 코드를 작성하는 과정에서 애플리케이션 개발자는 Connection, PrepareStatement, ResultSet 객체를 제어할 필요가 없다는 사실을 확인 할 수 있다.


 <리스트 5>iBatis Sql Maps 트랜잭션 예제



iBatis Sql Maps의 위치
요즘 Object Relational Mapping(이하 ORM)이라는 자주 듣게 된다. ORM은 객체 지향 데이터와 관계형 데이터베이스의 데이터를 연결시켜 주는 기술이다. SQL문을 사용하지 않고 데이터베이스로부터 데이터를 조회하고 애플리케이션 객체의 상태가 변함에 따라 데이터베이스에 변경 사항이 바로 저장되도록 하는 것이다.

객체 지향 언어에서 객체는 3차원 데이터이다. 단일 객체와 리스트가 섞여 있고 단일 객체는 또 따른 객체와 리스트를 저장할 수 있다. 반면 관계형 데이터베이스는 2차원 데이터로 컬럼과 로우로 구성되어 있다. 2차원 데이터를 읽어와 삼차원 데이터로 변경하는 작업은 SQL문을 이용하는 전통적인 방법이다.

ORM 기술로 유명한 툴들로 EJB, 하이버네이트, TopLink, JDO 등이 있다. ORM 기술이 많은 장점을 갖고 있는 것 같지만 현실에 적용해 보면 문제점이 많다. 프로젝트에 참여하는 인력의 대부분은 관계형 데이터베이스 관점에서 데이터를 바라보는데 익숙하고 SQL문을 사용하는 JDBC 코딩에 익숙한 것이 사실이다.

이런 상황에서 과도하게 ORM 기술을 적용할 경우 혼란만 가중시키는 경우가 대부분이다. 그러나 기존 방식대로 방대한 SQL문에 비즈니스 로직이 담겨있고, SQL문이 개발 코드와 섞여 있는 것은 SQL문 관리나 재사용성을 떨어뜨리는 문제를 가진다.

iBatis Sql Maps는 기존 JDBC 코드의 비효율성을 획기적으로 개선하는 동시에 JDBC 코드의 패러다임은 그대로 유지하고 있다. ORM 기술과 비교할 수는 없지만 조회 결과를 SQL 맵핑 정보에 따라 특정 객체에 설정하고 반환하는 부분을 자동화하고 있다. 또, SQL문을 중앙 집중적으로 관리할 수 있는 방안도 제공한다.

그뿐 아니다. 자체 데이터 캐시 기능을 포함하고 있고 XML문에 기술된 SQL문을 데이터의 상태에 따라 동적으로 변경하는 Dynamic SQL문을 제공한다. Log4j 설정을 할 때에는 자세한 내부 로그도 제공한다.

데이터베이스 벤더 별로 개별적으로 제공하는 모든 SQL 문의 표현 방식, 프로시저, 특정 함수들을 모두 지원한다. 이렇듯 iBatis Sql Maps는 ORM의 특성과 기존 JDBC 코드의 단점을 보안하고 장점을 흡수하는 중간적인 위치에 존재하는 퍼시스턴스(Persistence) 레이어 프레임워크이다.

  웹 애플리케이션 보안 프레임워크 - Acegi Security

Acegi Security(이하 Acegi) 프레임워크는 스프링 프레임워크의 서브 프로젝트로 개발되고 있는 보안 오픈소스 프레임워크이다. Acegi는 스프링 프레임워크의 공인 서브 프로젝트이며 http://acegisecurity.org 에서 운영되고 있는 오픈소스 프로젝트다.

스프링 프레임워크를 기반으로 AOP의 개념을 추가하여 만들어지는 만큼 모듈성과 이식성이 매우 뛰어나다는 장점을 가지고 있다. 보안은 처음에 상당히 부담되는 용어들을 많이 접하게 되는 분야이다. 이러한 탓에 Acegi 또한 처음에 적응하는데 상당히 어렵게 느껴지는 것이 사실이다. 여기에서는 Acegi가 나오게 된 이유와 그 사용법들에 대해 간단히 알아보자.

표준 웹 컨테이너 보안 메커니즘
Acegi를 살펴보기 전에 자바 웹 애플리케이션의 보안 표준은 없는 것일까? 당연히 있다. JAAS(Java Authentication and Authorization Service) 표준이 존재한다. 또한 Java EE 기반 웹 컨테이너는 인증(Authentication)과 권한(Authorization)을 처리하는 메커니즘을 포함하고 있다.

이 메커니즘을 CMA(Container Managed Authentication)라고 한다. CMA는 BASIC, Form-BASED, Mutual Authentication(상호 인증)의 세 가지 유형을 지원한다. 여기에서는 Form-Based 인증 위주로 살펴 볼 것이다. 톰캣(Tomcat)에서 CMP를 사용하려면 <리스트 6>과 같이 web,xml과 server.xml을 수정해 주어야한다.

web.xml에 를 FORM으로 설정된 웹 애플리케이션에 action이 j_security_check인 리퀘스트가 전달되면 CMA 메커니즘이 실행된다. CMA 메커니즘은 server.xml의 설 정을 통해서 j_security_chech 폼의 j_username과 j_password 파라미터를 이용하여 인증을 처리하고 인증처리가 성공적이면 인증 사용자의 권한을 조회한다. 톰캣은 JDBCRealm, DataSourceRealm, JNDIRealm, MemoryRealm, JAASRealm을 지원한다.

<리스트 6>은 JDBCRealm의 설정 예제이다. web.xml의 은 웹 애플리케이션 자원의 접근 권한을 정의한다. <리스트 6>은 URL이 ‘/admin/*’ 패턴인 자원은 ‘manager’ 권한이 있을 경우에만 접근할 수 있도록 하는 설정이다.

인증이 완료된 사용자의 리퀘스트가 의 패턴과 매치될 경우, 인증된 사용자가 ‘manager’ 권한을 가지고 있으면 해당 자원의 접근을 허용하고 권한이 없으면 접근을 제한한다.

CMA를 사용할 경우 인증과 권한에 대한 별도의 개발 과정 없이 WAS(Web Application Server)에 내장된 메커니즘을 이용하여 처리할 수 있다는 장점을 갖는다. CMA는 리퀘스트 인증과 권한 과정을 완료한 뒤에 인증과 권한 정보를 EJB 컨테이너에서도 사용할 수 있다.

또, HttpServletRequest.getRemoteUser(), HttpServletRequest.getUserPrincipal(), HttpServletRequest.isUserInRole(String role)를 이용하여 프로그램 적으로 인증 및 권한 정보를 사용할 수 도 있다.


 <리스트 6> 톰캣 CMA를 사용하기 위한 예제



CMA가 좋은 것 아닌가?
보안의 가장 중요한 요소는 인증과 권한이다. 이러한 보안은 대부분의 애플리케이션에서 기본적으로 제공되어야 하는 필수기능이다. 폼 이름과 필드 명을 맞추고 서버에 설정을 하는 것만으로 WAS에서 제공하는 보안 메커니즘을 사용할 수 있는 CMA는 정말 좋기만 한 것일까? CMA는 정말 좋은 기능이다.

그러나 모든 상황에서 좋을 수는 없다. CMA를 사용하면 CMA이전에 리퀘스트를 전 처리하기 위한 filter를 설정할 수가 없다. 또 이식성이 떨어진 다는 것도 CMA의 큰 단점이다.

톰캣과 레진을 WAS로 사용할 경우 간단한 방법으로 CMA 설정할 수는 있지만, 톰캣과 레진의 CMA 설정 방식은 전혀 다르다. 웹 로직이나 웹 스피어 같은 경우 설정에 필요한 XML에 접근할 수 없고 제공하는 콘솔로 설정해야 한다. 이 경우에는 설정하는 방식 자체가 다르다. 기존에 톰캣 상에서 <리스트 6>과 같이 JDBCRealm으로 개발된 애플리케이션이 있다.

이것을 웹 로직에 포팅 하는 것은 쉽지 않다. 웹 로직은 JDBC 기반의 Realm을 지원하지 않는다. 웹 로직은 기본적으로 LDAP 기반의 Realm만을 지원한다. 보안 측면의 기능은 WAS별로 다른 방식과 절차로 설정되어야 한다는 어려움이 있다. 동일한 메커니즘을 제공하지 않는 경우도 있다. 따라서 CMA을 사용할 경우 이식성이 떨어지는 결과를 낳는 것이다.

애플리케이션 레벨 보안
앞서 이야기 한 것처럼 Acegi는 스프링 프레임워크를 기반으로 개발된 보안 프레임워크이다. Acegi는 필터를 이용하여 URL 검사를 하고, 사용자 로그인 및 역할을 할당하고 비즈니스 로직 메소드의 사용자 권한 검사하는 역할을 담당한다.

Acegi가 스프링 기반으로 만들어졌다고는 하지만 꼭 스프링을 사용하는 웹 애플리케이션에만 적용할 수 있는 것은 아니다. Acegi는 사용자 인증과 권한을 처리 대상으로 한다.

사용자 인증은 웹 애플리케이션의 필터를 통해서 인증 대상 리퀘스트를 처리한다. 사용자를 구분하기 위하여 Principal을 사용하고 인증을 하기 위하여 Credentials를 사용한다. Principal과 Credentials라는 용어가 생소할 것이다. 이것은 폼 기반 인증에서 사용되던 id와 패스워드를 의미한다.

보안측면에서 사용자를 구분하고 확인 하는 방법은 매우 다양하다. 폼 기반의 아이디/패스워드가 일반적이지만, 이것은 사용자를 구분하고 확인하는 보안의 다양한 방법 중에 하나일 뿐이다.

Acegi는 HTTP Basic 방식, HTML Form 태그 방식, 싱글사인온(CAS, Central Authentication Service만을 지원) 방식을 기본으로 지원한다. 그 외의 인증 방식을 사용할 수 있도록 확장성도 제공한다. 따라서 사용자 구분과 확인 정보를 Principal과 Credentials로 표현한다. Acegi는 AOP를 이용하여 메소드 실행 전후에 권한을 체크한다.

●웹 애플리케이션 Acegi web.xml 설정
웹 애플리케이션에서 Acegi를 사용하기 위해서는 web.xml에 <리스트 7>과 같은 설정을 해야 한다. Acegi는 스프링 프레임워크를 사용한다. 가 바로 스프링 프레임워크를 설정하는 과정이다.

설정을 통해서 모든 HTTP 리퀘스트는 FilterToBeanProxy 필터로 전달된다. FilterToBeanProxy는 등록된 필터들을 순차적으로 실행하여 보안 체크를 처리한다.


 <리스트 7>웹 애플리케이션에 Acegi를 적용하기 위한 web.xml 설정



●Acegi 설정 – filterChainProxy
web.xml에 설정된 FilterChainProxy 필터는 applicationContext-acegi-security.xml에 등록된 filterChainProxy 빈을 사용한다. <리스트 8>은 filterChainProxy의 설정 예제이다. org.acegisecurity.util.FilterChainProxy 클래스를 반드시 ‘filterChainProxy’로 등록해야 한다. filterChainProxy는 HTTP 리퀘스트를 처리 할 순차적인 필터들이 등록된다.

<리스트 8>에서 ‘CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON’은 현재 URL을 모두 소문자로 전환하라는 명령이다. ‘PATTERN_TYPE_APACHE_ANT’은 처리할 URL 패턴을 등록하는 방식으로 정규 표현식 대신 ANT 스타일의 패턴을 사용하겠다는 의미이다.

‘/**’ 패턴에 일치하는 리퀘스트에 대하여 다음에 정의된 열 개의 필터를 등록된 순서대로 실행하라는 의미이다.


 <리스트 8> applicationContext-acegi-security.xml의 FilterChainProxy 설정



Acegi 필터와 자원 접근 설정
<리스트 8>의 설정 중에서 주로 사용되는 네 개의 빈에 대해 조금 더 자세히 살펴보자. 여기에서 알아 볼 네 개의 빈은 AuthenticationProcessingFilter와 HttpSessionContextIntegrationFilter, ExceptionTranslationFilter 그리고 FilterSecurityInterceptor이다. 각 빈의 역할에 대해 알아보자.

●AuthenticationProcessingFilter
authenticationProcessingFilter는 URL(authenticationFailureUrl) 인증이 실패했을 경우에 이동할 URL(filterProcessesUrl)을 설정한다. 또한 인증 절차를 어떻게 설정할 것인가를 등록하는데 이것이 바로 authenticationManager이다. AuthenticationManager를 통해서 사용자의 Principal과 Credentials가 정확한 지 파악하고 적절한 처리를 수행하게 된다.


 <리스트 9> applicationContext-acegi-security.xml의 AuthenticationProcessingFilter 설정



<리스트 9>의 authenticationProcessingFilter 빈은 authenticationManager 빈에 의존성을 가지고 있음을 확인할 수 있다. autenticationManager 빈 이하의 의존성은 <리스트 10>과 같다. authenticationManager는 인증을 처리하는 복수의 Provider를 포함하고 순차적으로 Provider에게 인증 절차를 위임하는 역할만을 한다.

authenticationManager 예제에서 사용하는 Provider는 DaoAuthenticationProvider를 사용하고 있다. DaoAuthenticationProvider는 메모리와 해시, 데이터베이스에 저장된 데이터를 인증하는 기능을 제공한다. DaoAuthenticationProvider는 userDetailsService에 어떤 저장소를 사용할 것인가를 설정한다.

<리스트 10>은 <리스트 12>의 users.properties 정보를 메모리에 관리하는 userDetailsService빈을 사용하도록 설정된 예제이다. Acegi에서 사용하는 인증의 핵심 인터페이스는 Authentication과 AuthenticationManager이다.

ProviderManager는 AuthenticationManager의 구현 클래스이다. Authentication은 내부적으로 세 개의 주요 멤버 변수를 가진다. 이 멤버 변수는 Principal, credentials, authorities 배열이다. Principal은 사용자의 구분자(ID), credentials는 인증을 확인하기 위한 데이터(패스워드)이고 credentials는 사용자 롤을 저장한다.

authenticationProcessingFilter가 실행될 때 authenticationProcessingFilter는 principal과 credentials를 이용하여 Authentication 객체를 생성한다. 이때까지 credentials 배열은 초기화 된 상태이다. authenticationProcessingFilter는 AuthenticationManager.authenticate(Authentication) 이용하여 Authentication 객체의 credentials를 설정하여 완전한 Authentication 객체를 만들게 된다.


 <리스트 10> ProviderManager와 의존성 예제




 <리스트 11> user.properties 예제



●HttpSessionContextIntegrationFilter
HttpSessionContextIntegrationFilter는 Acegi의 SecurityContext를 서블릿 세션과 연결하는 역할을 담당한다. 사용자의 Authentication 객체를 매번 만드는 것은 비효율적이다. Acegi는 Authentication을 저장하고 재사용한다. Acegi는 SecurityContextHolder의 ThreadLocal 멤버 변수에 SecurityContext를 저장한다.

<리스트 12>는 애플리케이션에서 Authentication 객체를 사용하기 위해 얻어오는 코드와 HttpSessionContextIntegrationFilter를 설정하는 XML의 예제이다.


 <리스트 12> HttpSessionContextIntegrationFilter 스프링 빈 설정 예제 및 코드



●ExceptionTranslationFilter
ExceptionTranslationFilter는 예외 상황이 발생한 경우 어떻게 처리할 것인가를 정의한다. 인증이 되지 않아서 예외가 발생한 경우라면 <리스트 13>에서는 ‘/acegilogin.jsp’가 전달된다. 반면 권한이 없어서 예외가 발생한 상황이라면 ‘/accessDenied.jsp’가 전달된다.


 <리스트 13> ExceptionTranslationFilter의 스프링 빈 설정 예제



●FilterSecurityInterceptor
FilterSecurityInterceptor는 보안 대상 자원을 설정하는 부분이다. <리스트 14>에서는 objectDefinitionSource에서 사용할 자원의 권한을 설정한다. HTTP 리퀘스트 URL을 모두 소문자로 바꾸고 ant 스타일의 패턴을 사용하겠다는 설정을 하고 있다. 또, ‘/secure/extreme/’이하의 URL은 ROLE_SUPERVISOR 권한을 갖는 사용자만 접근 가능하도록 설정하는 예제이다.

현재 HTTP 리퀘스트의 사용자가 아직 인증 받지 않았다면 authenticationManager를 사용하여 인증 절차를 거친다. 인증 절차를 거치고 권한 정보를 수집한 뒤에 objectDefinitionSource을 확인하여 accessDecisionManager가 현재 사용자의 접근 여부를 결정하게 된다.


 <리스트 14> FilterSecurityInterceptor 의 스프링 빈 설정 예제



Acegi와 친해지기
Acegi는 자바 플랫폼에 사용 가능한 보안 프레임워크 중 최고의 걸작이다. 이 번호에서는 Acegi 프레임웍에 적응하기 위한 가장 기본적인 설정법과 기본 개념만을 살펴보았다. Acegi 프레임워크가 좋기는 하지만 처음에 접근하는 것은 쉽지 않은 것이 사실이다. CMA에 대하여 전반적으로 살펴보고 싶다면 ‘J2EE Form-based Authentication’ (http://www.onjava.com/pub/a/onjava/2002/06/12/form.html)을 추천한다.

Acegi 자체에 대한 자료로는 www.acegisecurity.org에서 제공하는 레퍼런스 매뉴얼이 가장 좋은 자료지만 그 자료를 접하기 전에 http://www.acegisecurity.org/articles.html에 정리된 문서를 읽어보는 것을 추천한다. 이곳에는 블로그나 기타 웹 문서로 존재하는 주요 자료의 리스트를 제공한다.

이 중에서 ‘Securing Your Java Applications - Acegi Security Style’는 반드시 읽어 보는 것이 좋다. 이 문서를 번역한 문서는 ‘http://openframework.or.kr/JSPWiki/Wiki.jsp?page=SecuringYourJavaApplications’ 에 있다.

마지막으로 자바지기 위키(http://wiki.javajigi.net/)에 Spring Framework 강좌에 Acegi의 전반적인 개념을 정리한 문서를 제공하고 있다. 또한 2006년 1월부터 3개월간 마소에 연재된 ‘Acegi Security’ 연재를 통해서 acegi의 전반적인 개념을 잡을 수 있을 것이다.

이 문서들을 살펴보고 SpringFrmaework의 Reference Manual을 읽어보는 것이 가장 효과적인 접근법이라고 생각한다. @

출처 : http://www.zdnet.co.kr/builder/dev/web/0,39031700,39160907,00.htm