[java] Apache Shiro와 LDAP 연동

Apache Shiro는 자바 기반의 강력한 보안 및 인증 프레임워크로, 다양한 인증 및 권한 관리 기능을 제공합니다. LDAP (Lightweight Directory Access Protocol)는 네트워크를 통해 디렉터리 서비스를 제공하는 프로토콜입니다. 이번 블로그에서는 Apache Shiro와 LDAP를 연동하여 사용자 인증 및 권한 관리를 어떻게 수행하는지 알아보겠습니다.

LDAP 서버 설정

먼저, LDAP 서버를 설정해야 합니다. 이를 위해 OpenLDAP과 같은 LDAP 서버를 사용할 수 있습니다. LDAP 서버에는 사용자 및 그룹 정보가 저장되며, 클라이언트(여기서는 Apache Shiro)는 이 정보를 사용하여 인증 및 권한 검사를 수행합니다. LDAP 서버의 구성과 사용자/그룹 정보를 생성하는 방법에 대해서는 여기서 다루지 않을 것입니다. 이해를 돕기 위해 간단한 LDAP 트리 구조를 예시로 살펴보겠습니다:

- dc=example,dc=com
  - ou=users
    - uid=user1
      - cn: User 1
      - userPassword: password1
      - memberOf: cn=admin,ou=groups
  - ou=groups
    - cn=admin
      - member: uid=user1,ou=users

이 예시에서는 “user1”이라는 사용자가 “admin” 그룹에 속해 있음을 나타냅니다.

Apache Shiro 의존성 추가

Apache Shiro를 사용하기 위해, 먼저 프로젝트에 Apache Shiro의 의존성을 추가해야 합니다. Maven을 사용하는 경우, pom.xml 파일에 다음 의존성을 추가할 수 있습니다:

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-core</artifactId>
    <version>1.7.1</version>
</dependency>

Shiro 설정 파일 구성

Apache Shiro의 설정은 shiro.ini 또는 shiro.properties 파일을 통해 구성할 수 있습니다. 여기서는 shiro.ini 파일을 사용하는 예시를 보여드리겠습니다.

[main]
ldapRealm = org.apache.shiro.realm.ldap.JndiLdapRealm
ldapRealm.contextFactory.url = ldap://localhost:389
ldapRealm.contextFactory.authenticationMechanism = SIMPLE
ldapRealm.userDnTemplate = uid={0},ou=users
ldapRealm.authorizationEnabled = true
ldapRealm.groupRolesMap = "cn=admin,ou=groups":"admin"

[users]
# 사용자별로 설정할 수 있는 일반적인 사용자 권한을 추가할 수 있습니다.

[roles]
# 사용자 그룹에 대한 역할 권한을 추가할 수 있습니다.

[urls]
# URL 별로 접근 제한을 설정할 수 있습니다.

위의 설정 파일에서는 ldapRealm을 통해 LDAP 서버와의 연동을 구성하고 있습니다. 여기서 ldapRealm.contextFactory.url은 LDAP 서버의 URL을 지정하고, ldapRealm.userDnTemplate은 사용자 DN 템플릿을 설정합니다. ldapRealm.authorizationEnabled은 사용자 그룹 기반의 인가를 사용할지 여부를 결정하며, ldapRealm.groupRolesMap은 그룹과 역할 권한 매핑을 정의합니다.

Apache Shiro를 사용하여 인증 및 접근 제어 수행

Apache Shiro로 인증 및 접근 제어를 수행하려면, 다음과 같은 코드를 사용할 수 있습니다:

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;

public class Main {
    public static void main(String[] args) {
        // Shiro SecurityManager 생성
        Factory<org.apache.shiro.mgt.SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
        org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance();
        SecurityUtils.setSecurityManager(securityManager);

        // 인증
        Subject currentUser = SecurityUtils.getSubject();
        if (!currentUser.isAuthenticated()) {
            UsernamePasswordToken token = new UsernamePasswordToken("user1", "password1");
            try {
                currentUser.login(token);
                System.out.println("인증 성공");
            } catch (UnknownAccountException uae) {
                System.out.println("계정을 찾을 수 없음");
            } catch (IncorrectCredentialsException ice) {
                System.out.println("잘못된 비밀번호");
            } catch (LockedAccountException lae) {
                System.out.println("계정이 잠겨 있음");
            } catch (AuthenticationException ae) {
                System.out.println("인증 실패");
            }
        }

        // 접근 제어
        if (currentUser.hasRole("admin")) {
            System.out.println("관리자 권한이 있음");
        } else {
            System.out.println("관리자 권한이 없음");
        }

        currentUser.logout();
    }
}

위의 코드에서는 shiro.ini 설정 파일을 사용하여 SecurityManager를 생성하고, currentUser를 통해 인증 및 접근 제어를 수행합니다. 사용자 인증에 성공하면 “인증 성공”이라는 메시지가 출력되며, currentUser.hasRole("admin")을 통해 사용자의 역할 권한을 확인할 수 있습니다.

이로써 Apache Shiro와 LDAP의 연동에 대해 알아보았습니다. Apache Shiro는 다양한 인증 및 권한 관리 기능을 제공하기 때문에, 보안을 강화하고자 하는 Java 애플리케이션에 적용할 수 있는 훌륭한 선택입니다.

참고 자료