저자 Shing Wai Chan  

Java EE 5 이전에는 배포 설명자에서만 웹 계층 구성요소 및 Enterprise JavaBeans 기술 구성요소(일명 enterprise bean)에 대한 인증 및 권한 부여 정보를 지정할 수 있었다. 하지만 Java EE 5는 보안 주석을 통합하여 작업을 단순화했다. 이러한 주석은 JSR 250: 자바 플랫폼에 대한 일반 주석에 지정되어 있다.

이 주석은 enterprise bean 및 웹 구성요소에 대한 권한 부여를 단순화한다. 이 단순화는 enterprise bean에서 특히 중요하다.

이 테크팁에서는 보안 주석을 사용하여 보호되는 enterprise bean의 구성 방법을 살펴보겠다. 또한 애플리케이션 클라이언트에서 enterprise bean에 액세스하는 방법도 살펴보겠다.

샘플 웹 애플리케이션 패키지가 이 팁에 제공된다. 이 팁의 코드 예제는 해당 패키지에 포함된 샘플의 소스 코드에서 따온 것이다.

간단한 예제

간단한 enterprise bean(이 경우, PingEjb라는 무상태 세션 빈)을 먼저 작성해 보고 권한 부여 검사를 포함해 보자.

   @Remote({Ping.class})
   @Stateless
   public class PingEjb implements Ping {

       @PermitAll
       public String pingPermitAll() {
           return "PingEjb: pingPermitAll";
       }

       @DenyAll
       public String pingPermitAll() {
           return "PingEjb: pingDenyAll";
       }

       @RolesAllowed({"staff"})
       public String ping() {
           return "PingEjb: ping";
       }
   }

PingEjb에서 @PermitAll, @DenyAll@RolesAllowed의 3가지 보안 주석을 주목하기 바란다. 사실 Java EE 5에서는 5개의 보안 주석이 도입되었다. 방금 언급한 3가지 주석 외에 @DeclareRoles@RunAs가 있다. 5개의 모든 보안 주석은 javax.annotation.security 패키지에 있다.

@PermitAll을 사용하면 모든 보안 역할에서 연관된 메소드를 호출할 수 있다. @DenyAll을 사용하면 모든 보안 역할에서 연관된 메소드를 호출할 수 없다. PingEjb@RolesAllowed 주석은 ping 메소드에 적용된다. 여기서는 "staff" 역할을 가진 사용자만 이 메소드에 액세스할 수 있다.

보다 복잡한 예제

앞의 예제에서는 @RolesAllowed를 사용하여 enterprise bean에서 메소드를 보호하기가 얼마나 쉬운지 살펴보았다. 다음은 보다 복잡한 예제이다.

   @RunAs(value="staff")
   @DeclareRoles({"staff", "temporary"})
   @RolesAllowed({"ttrole"})
   @Stateless
   public class HelloEjb implements Hello {
       @Resource private SessionContext sc;
       @EJB private Ping ping;

       public String hello() {
           if (!sc.isCallerInRole("staff") &&
                  !sc.isCallerInRole("temporary")) {
               return "HelloEjb: hello";
           } else {
               throw new RuntimeException(
                      "of role staff or temporary");
           }
       }

       @RolesAllowed({"myrole"})
       public String ping() {
           return ping.ping();
       }
   }

HelloEjb 예제에는 두 개의 @RolesAllowed 주석이 있는데, 하나는 클래스 레벨이고 다른 하나는 메소드 레벨이다. 클래스 레벨의 @RolesAllowed 주석은 bean의 모든 비즈니스 메소드에 적용된다. 하지만 이 주석은 보다 구체적인 메소드 레벨의 보안 주석이 있는 경우 재정의될 수 있다. hello 메소드에는 보안 주석이 없으므로 이 메소드는 클래스 레벨의 주석 @RolesAllowed({"ttrole"})에 종속된다. 하지만 ping 메소드는 메소드 레벨의 주석 @RolesAllowed({"myrole"})에 종속된다.

@RunAs 주석은 메소드 호출 내의 후속 호출에 대한 역할을 지정하지만 메소드의 직접 호출에 대한 역할은 지정하지 않는다. 예제에서 HelloEjb.ping()은 로그인 사용자 역할을 가진 사용자라기보다 "staff" 역할을 가진 사용자로서 Ping.ping() 메소드를 호출한다.

@DeclareRoles 주석은 구성요소가 사용하는 역할을 정의하기 위해 사용된다. HelloEjb에서 "staff" 및 "temporary" 역할은 hello 메소드 내에서 isCallerInRole()의 호출에 의해 사용될 수 있다. isCallerInRole() 메소드는 @RolesAllowed보다 복잡한 보안 검사를 제공한다. HelloEjb에서는 "ttrole" 역할을 가진 사용자만 hello() 메소드에 액세스할 수 있다. "staff" 또는 "temporary" 역할을 가진 사용자는 이 메소드에 액세스할 수 없다.

다음 두 예제는 보안 관점에서 기능적으로 동일하다는 사실에 주목하기 바란다.

   @RolesAllowed("staff")
   public String dummy() {
       ...
   }

and:

   @DeclareRoles({"staff"})
   ...
   public String dummy() {
       if (!sc.isCallerInRole("staff")) {
           throw RuntimeException("Not authorized");
       }
       ...
   }

클라이언트 작성하기

이제 앞의 예제에서 살펴본 enterprise bean을 사용하는 클라이언트 자바 기술 프로그램을 작성해 보자. 다음은 클라이언트 코드의 단편이다. 샘플 패키지에서 전체 코드를 찾을 수 있다.

   public class Client {
       private static @EJB Ping ping;
       private static @EJB Hello hello;

       public static void main(String arg[]) {
           System.out.println(
                  "Calling Ping.pingPermitAll(): ... " +
                  ping.pingPermitAll());  

           try {
               System.out.println(
                      "Calling Ping.pingDenyAll(): ... " +
                      ping.pingDenyAll());
           ...

           try {
               System.out.println(
                      "Calling Ping.ping(): ... " +
                      ping.ping());

           ...

           System.out.println("Calling Hello.hello(): ... " +
                  hello.hello());
           System.out.println("Calling Hello.ping(): .... " +
                  hello.ping());
   ...

클라이언트 프로그램은 보안이 지정되지 않은 것처럼 동일한 방식으로 enterprise bean에 액세스한다는 사실에 주목하기 바란다. 이 프로그램은 @EJB 주석을 사용하여 bean을 찾는다.

  private static @EJB Ping ping;
  private static @EJB Hello hello;

그리고 일반적인 방식으로 enterprise bean 메소드를 호출한다.

  hello.hello();
  hello.ping()

배포 설명자에서 보안 정보 지정하기

보안 주석이 인증 및 권한 부여를 단순화하기는 하지만 배포 설명자에서 일부 보안 관련 정보를 지정해야 한다. 다행히도 주석을 사용하고 기본 설정에 의존하면 배포 설명자에 지정해야 하는 보안 관련 정보의 양은 크게 줄어든다. 권한 부여를 사용하는 애플리케이션의 경우 여전히 배포 설명자에 security-role-mapping을 설정해야 한다.

Java EE 환경은 권한 부여를 위한 역할을 사용한다. 하지만 많은 운영 체제 환경에서 사용자들은 그룹과 연관되어 있다. security-role-mapping은 사용자 역할 개념과 principal 또는 그룹 사이의 링크를 제공한다. 이 매핑을 통해 principal-name 또는 group-namerole-name과 연관시킬 수 있다. Java EE 5 SDK의 썬 자바 시스템 애플리케이션 서버와 같은 Java EE 5 애플리케이션 서버 구현에서는 security-role-mappingsun-application.xml 파일에 정의한다. 다음은 그 예제이다.

   <sun-application>
     <security-role-mapping>
       <role-name>ttrole</role-name>
       <group-name>ttgroup</group-name>
     </security-role-mapping>
     <security-role-mapping>
       <role-name>myrole</role-name>
       <principal-name>ttuser</principal-name>
     </security-role-mapping>
     <security-role-mapping>
       <role-name>staff</role-name>
       <principal-name>aprincipal</principal-name>
     </security-role-mapping>
     <security-role-mapping>
       <role-name>temporary</role-name>
       <principal-name>noone</principal-name>
     </security-role-mapping>
   </sun-application>

사용자는 애플리케이션에 사용된 각 역할에 대한 매핑을 정의해야 한다. @RunAs의 역할에서 sun-ejb-jar.xml에 principal이 정의되어 있지 않으면 애플리케이션 서버는 security-role-mapping의 principal을 사용한다. 다음은 HelloEjb enterprise bean에 대한 run-as principal을 sun-ejb-jar.xml 파일에 정의하는 예제이다.

   <sun-ejb-jar>
     <enterprise-beans>
       <ejb>
         <ejb-name>HelloEjb</ejb-name>
         <principal>
           <name>aprincipal</name>
         </principal>
       </ejb>
     </enterprise-beans>
   </sun-ejb-jar>  

@RolesAllowed 주석을 사용하는 경우에는 애플리케이션 서버가 배포 설명자에서 <ior-security-config> 요소에 대한 기본값을 제공한다. 기본 <ior-security-config> 요소에는 username_password<auth-method> 요소 값과 인증을 위한 기본 영역이 제공된다. sun-application.xml 파일에서 다음과 같이 <security-role-mapping> 요소 다음에 <realm> 요소를 추가하여 이를 사용자 정의할 수 있다.

   <realm>file</realm>

샘플 코드 실행하기

  1. Java EE 5 SDK가 없으면 Java EE Downloads 페이지에서 Java EE 5 SDK를 다운로드하여 설치한다.

  2. 다음 환경 변수를 설정한다.

    • JAVEE_HOME. 이 변수는 썬 자바 시스템 애플리케이션 서버의 설치 위치를 가리켜야 한다.

    • ANT_HOME. 이 변수는 ant의 설치 위치를 가리켜야 한다. Ant는 Java EE 5 SDK에 포함된 썬 자바 시스템 애플리케이션 서버에 포함되어 있다. (Windows에서는 lib\ant 하위 디렉토리에 있음)

    • JAVA_HOME. 이 변수는 사용자 시스템의 JDK 5.0 위치를 가리켜야 한다.

    $JAVA_HOME/bin, $ANT_HOME/bin$JAVAEE_HOME/bin을 사용자의 PATH 환경 변수에 추가한다.

  3. 팁에 대한 샘플 패키지를 다운로드하고 해당 컨텐츠의 압축을 푼다. 이제 압축이 풀린 디렉토리가 <sample_install_dir>/ejb-secann과 같이 나타난다. 여기서 <sample_install_dir>는 샘플 패키지를 설치한 디렉토리이다. 예를 들어, Windows 시스템의 C:\ 경로에 해당 컨텐츠의 압축을 풀었다면 새로 생성된 디렉토리는 C:\ejb-secann이 되어야 한다.

  4. ejb-secann 디렉토리로 변경하고 build.properties 파일을 적절하게 편집한다. 예를 들어, admin 호스트가 원격인 경우 admin.host의 값을 기본값(localhost)에서 적절한 원격 호스트로 변경한다. 또한 다음 등록 정보가 올바르게 지정되었는지 확인한다.

    • admin.user. 도메인을 시작 및 중지하는 관리자의 ID이다.

    • admin.port. 관리 서버의 http 포트 번호이다.

  5. passwd 파일에서 AS_ADMIN_PASSWORD 값을 관리자 비밀번호로 업데이트한다. AS_ADMIN_USERPASSWORD는 테스트를 위해 생성된 사용자의 비밀번호이다. 이 값을 변경하는 경우 실행 대상의 해당 값도 업데이트한다.

  6. 다음 명령을 입력하여 애플리케이션 서버를 시작한다.

      <appserv_install>/bin/asadmin start-domain domain1

      여기서 <appsrv_install>은 애플리케이션 서버를 설치한 위치이다.

  7. 다음 명령을 입력하여 사용자(ttuser)를 애플리케이션 서버의 기본 영역에 생성한다.

      ant create-user

  8. 샘플을 빌드하고 배포한다. 먼저 다음 명령을 입력한다.

        ant build

    그러면 enterprise bean 및 서블릿 웹 서비스 클래스가 컴파일되고 ear 파일이 생성된다.

    그리고 다음 명령을 입력한다.

        ant deploy

    그러면 ear 파일이 애플리케이션 서버에 배포된다.

  9. 클라이언트 애플리케이션을 실행하여 EJB에 액세스한다. 다음 명령을 입력한다.

         ant run

    다음과 같은 결과가 나타나야 한다.

          [exec] Calling Ping.pingPermitAll(): ...
              PingEjb: pingPermitAll
          [exec] Expected failure for any call of Ping.pingDenyAll()
          [exec] Expected failure for direct call of Ping.ping()
          [exec] Calling Hello.hello(): ... HelloEjb: hello
          [exec] Calling Hello.ping(): .... PingEjb: ping

    Ping.ping()의 직접 호출은 실패할 것이다. 사용자 ttuserttgroup 그룹에 있으며 이 그룹은 myrolettrole 역할을 가지고 있고 Ping.ping() 메소드는 권한 부여를 위해 staff 역할을 필요로 하기 때문이다.

  10. 다음 명령을 입력하여 EJB ear 파일을 배포 해제할 수 있다.

      ant undeploy

  11. 애플리케이션을 배포 해제한 후 다음 명령을 입력하여 테스트용 사용자를 제거한다.

      ant delete-user

저자 정보

Shing Wai Chan은 썬 자바 시스템 애플리케이션 서버 및 Java EE SDK 개발 팀의 멤버입니다. 그는 지난 몇 년 동안 Java EE 보안에 관여해 왔습니다.

"Java EE" 카테고리의 다른 글

2007/05/28 17:41 2007/05/28 17:41

TRACKBACK :: http://blog.sdnkorea.com/blog/trackback/388

댓글을 달아 주세요

  1. 고진구  수정/삭제  댓글쓰기

    자바는 알면 알수록 재미가 있어지네요. 좋은 자료 잘 활용하겠습니다.

    2007/09/13 22:41
  2. 박정숙  수정/삭제  댓글쓰기

    좋은 정보 감사해요~

    2007/09/19 03:28
  3. 김문경  수정/삭제  댓글쓰기

    좋은 글,감사합니다

    2007/09/19 13:24
  4. 진정미  수정/삭제  댓글쓰기

    좋은 정보 감사합니다.
    많이 배우고 가요~

    2007/09/19 23:11
[로그인][오픈아이디란?]

◀ Prev 1  ... 255 256 257 258 259 260 261 262 263  ... 626  Next ▶