ヘッダーをスキップ
Oracle Fusion Middleware Oracle Identity Managementアプリケーション開発者ガイド
11gリリース1(11.1.1)
B56242-01
  目次
目次
索引
索引

戻る
戻る
 
次へ
次へ
 

5 JNDIに対するJava API拡張機能の使用

この章では、標準のディレクトリAPIにJavaの拡張機能を使用して、第3章で紹介した多くの操作を実行する方法について説明します。この章では使用例を示します。標準APIに対するOracleの拡張機能の詳細は、『Oracle Fusion Middleware Java API Reference for Oracle Internet Directory』を参照してください。

この章の項目は次のとおりです。

5.1 サンプル・コード

サンプル・コードは次のURLで入手できます。

http://www.oracle.com/technology/sample_code/

「Sample Applications–Oracle Application Server」の下の「Oracle Identity Management」リンクを探してください。

5.2 Java拡張機能のインストール

Java拡張機能は、LDAPクライアントのインストール時に標準のJava APIとともにインストールされます。APIとその拡張機能は、$ORACLE_HOME/jlib/ldapjclnt10.jarにあります。

5.3 oracle.ldap.utilパッケージを使用したLDAPオブジェクトのモデル化

Javaでは、LDAPエンティティ(ユーザー、グループ、レルム、アプリケーション)は、ハンドルではなくJavaオブジェクトとしてモデル化されます。このモデル化は、oracle.java.utilパッケージで行われます。他のすべてのユーティリィティ機能は、個々のオブジェクトとして(GUIDなど)、あるいはユーティリィティ・クラスの静的メンバー関数としてモデル化されます。

たとえば、ユーザーを認証するには、アプリケーションは次の手順に従います。

  1. 指定されたユーザー識別名で、oracle.ldap.util.Userオブジェクトを作成します。

  2. 必要なプロパティのすべてを備えたDirContext JNDIオブジェクトを作成するか、あるいはDirContextオブジェクトのプールからJNDIオブジェクトを取得します。

  3. User.authenticateUserメソッドを呼び出して、DirContextオブジェクトおよびユーザー資格証明への参照を渡します。

  4. 既存のDirContextオブジェクトのプールから取得したDirContextオブジェクトは、そのプールに戻します。

CやPL/SQLのプログラマとは異なり、Javaプログラマはオブジェクトを明示的に解放する必要がありません。このタスクは、Javaのガベージ・コレクション・メカニズムが実行します。

5.4 PropertySetCollection、PropertySetおよびPropertyクラス

Userクラス、SubscriberクラスおよびGroupクラスのほとんどのメソッドは、PropertySetCollectionオブジェクトを戻します。このオブジェクトは、1つ以上のLDAPエントリの集合を表しています。各エントリはPropertySetオブジェクトで表され、識別名で識別されます。PropertySetには、Propertyとして表される属性が含まれる場合があります。Propertyとは、そのPropertyが表す特定の属性に関する1つ以上の値の集合です。次に、これらのクラスの使用例を示します。

PropertySetCollection psc = Util.getGroupMembership( ctx,
                                                     myuser,
                                                     null,
                                                     true );
    // for loop to go through each PropertySet
    for (int i = 0; i < psc.size(); i++ ) {

    PropertySet ps = psc.getPropertySet(i);

   // Print the DN of each PropertySet
   System.out.println("dn:  " + ps .getDN());

   // Get the values for the "objectclass" Property
   Property objectclass = ps.getProperty( "objectclass" );


   // for loop to go through each value of Property "objectclass"
   for (int j = 0; j< objectclass.size(); j++) {

       // Print each "objectclass" value
       System.out.println("objectclass:  " + objectclass.getValue(j));
   }
}

エンティティmyuserは、Userオブジェクトです。pscオブジェクトには、myuserが属するネストされたグループがすべて含まれます。このコードは結果エントリをループし、各エントリのオブジェクト・クラス値をすべて出力します。

5.5 ユーザーの管理

ユーザー関連機能はすべてoracle.ldap.util.UserというJavaクラスで抽象化されます。このプロセスは、次のようになります。

  1. 識別名、GUIDまたは単純な名前に基づいて、oracle.ldap.util.Userオブジェクトを構成します。

  2. 必要な場合は、User.authenticateUser(DirContext, int, Object)を呼び出して、ユーザーを認証します。

  3. User.getProperties(DirContext)を呼び出して、ユーザー・エントリの属性を取得します。

  4. User.getExtendedProperties(DirContext, int, String[])を呼び出して、ユーザーの拡張プロパティを取得します。intは、共有またはアプリケーション固有です。String[]は、希望するプロパティのタイプを示すオブジェクトです。String[]がNULLの場合は、指定したカテゴリの全プロパティが取得されます。

  5. PropertySetCollection.getProperties(int)を呼び出して、手順4で戻されたプロパティの解析に必要なメタデータを取得します。

  6. 拡張プロパティを解析し、アプリケーション固有のロジックを続行します。この解析は、アプリケーション固有のロジックによっても行われます。

5.6 ユーザーの認証

ユーザー認証は、ユーザーがログイン時に指定した資格証明とそのユーザーのディレクトリ内の資格証明を比較する一般的なLDAP操作です。Oracle Internet Directoryでは、次のものがサポートされています。

次に、APIを使用してユーザーを認証するためのコード例を示します。

 // User user1 - is a valid User Object
        try
        {
                user1.authenticateUser(ctx,
                    User.CREDTYPE_PASSWD, "welcome");

                // or
                // user1.authenticateUser(ctx, <any
attribute>, <attribute value>);
        }
        catch (UtilException ue)
        {
                // Handle the password policy error
accordingly
                if (ue instanceof PasswordExpiredException)
                        // do something
                else if (ue instanceof GraceLoginException)
                        // do something
        }

5.7 ユーザーの作成

subscriberクラスによってcreateUser()メソッドが使用され、プログラムによりユーザーが作成されます。ユーザー・エントリに必要なオブジェクト・クラスは、Oracle Delegated Administration Servicesを介して設定可能です。createUser()メソッドは、ユーザーの作成時に、クライアントが要件を理解し必須の属性に対して値を提供することを前提にしています。プログラマによって必須情報が提供されない場合、サーバーはエラーを戻します。

コード例の次のスニペットは、使用方法を示します。

// Subscriber sub is a valid Subscriber object
// DirContext ctx is a valid DirContext

// Create ModPropertySet object to define all the attributes and their values.
ModPropertySet mps = new ModPropertySet();
mps.addProperty(LDIF.ATTRIBUTE_CHANGE_TYPE_ADD,"cn", "Anika");
mps.addProperty(LDIF.ATTRIBUTE_CHANGE_TYPE_ADD,"sn", "Anika");
mps.addProperty(LDIF.ATTRIBUTE_CHANGE_TYPE_ADD,"mail",
"Anika@example.com");

// Create user by specifying the nickname and the ModPropertySet just defined
User newUser = sub.createUser( ctx, mps, true);

// Print the newly created user DN
System.out.println( newUser.getDN(ctx) );

// Perform other operations with this new user

5.8 ユーザー・オブジェクトの取得

subscriberクラスによってgetUser()メソッドが提供され、Userクラスのパブリック・コンストラクタと置き換えられます。このメソッドは、指定された情報に基づいてUserオブジェクトを戻します。

次に、使用方法を示します。

// DirContext ctx is contains a valid directory connection with
sufficient privilege to perform the operations

// Creating RootOracleContext object
RootOracleContext roc = new RootOracleContext(ctx);

// Obtain a Subscriber object representing the default
subscriber
Subscriber sub = roc.getSubscriber(ctx,
Util.IDTYPE_DEFAULT, null, null);

// Obtain a User object representing the user whose
nickname is "Anika"
User user1 = sub.getUser(ctx, Util.IDTYPE_SIMPLE, "Anika",
null);
// Do work with this user

The getUser() method can retrieve users based on DN, GUID
and simple name.  A getUsers() method is also available to
perform a filtered search to return more than one user at a
time.  The returned object is an array of User objects.
For example,

// Obtain an array of User object where the user's nickname
starts with "Ani"
User[] userArr = sub.getUsers(ctx, Util.IDTYPE_SIMPLE,
"Ani", null);
// Do work with the User array

5.9 レルムからのオブジェクトの取得

この項では、Java APIを使用してアイデンティティ管理レルムのオブジェクトを取得する方法について説明します。

RootOracleContextクラスはルートOracleコンテキストを表します。アイデンティティ管理レルムの作成に必要な情報のほとんどは、ルートOracleコンテキストに格納されています。RootOracleContextクラスではgetSubscriber()メソッドが提供されます。このメソッドは、subscriberクラスのパブリック・コンストラクタと置き換えられ、指定された情報に基づいてアイデンティティ管理レルム・オブジェクトを戻します。

次に、使用方法を示します。

// DirContext ctx contains a valid directory
// connection with sufficient privilege to perform the
// operations

// Creating RootOracleContext object
RootOracleContext roc = new RootOracleContext(ctx);

// Obtain a Subscriber object representing the
// Subscriber with simple name "Oracle"
Subscriber sub = roc.getSubscriber(ctx,
Util.IDTYPE_SIMPLE, "Oracle", null);

// Do work with the Subscriber object

5.10 例: Oracle Single Sign-Onログイン名の検索

次の例では、単純な名前、GUIDまたはDNがわかっている場合にユーザーのログイン名を検索する方法を示します。Oracle Single Sign-Onのログイン名は、ニックネームとも呼ばれます。

この例は、2つの部分から構成されています。

  1. このレルムへのニックネームの保存に使用されている属性を確認します。

  2. ユーザー・オブジェクトを取得し、ニックネーム属性の値を確認します。

import javax.naming.*;
import javax.naming.directory.*;
import javax.naming.ldap.*;
import oracle.ldap.util.jndi.*;
import oracle.ldap.util.*;
import java.io.*;

public class NickNameSearch {

   public static void main(String[] args)
      throws Exception
   {
      InitialLdapContext ctx = ConnectionUtil.getDefaultDirCtx( args[0],
                                     args[1], args[2],args[3]);

      RootOracleContext roc=new RootOracleContext(ctx);
      Subscriber sub = null;
      sub = roc.getSubscriber(ctx, Util.IDTYPE_DEFAULT, null, null) ;

      PropertySetCollection psc = sub.getProperties(ctx,
                                     Subscriber.USER_NAMING_PROPERTIES, null);

      String nickNameAttribute = null;
      try
      {
          nickNameAttribute = (String) psc.getPropertySet(0)
.getProperty(Subscriber.USER_NAMING_ATTR_SIMPLE).getValue(0);
      }
      catch (Exception e)
      {
         // unable to retrieve the attribute name
         System.exit(0);
      }
      System.out.println("Nickname attribute: " + nickNameAttribute);

      // Retrieve user using simple name, guid or DN
      User user = sub.getUser(ctx, Util.IDTYPE_SIMPLE,"orcladmin", null);
      System.out.println("user DN: " + user.getDN(ctx));

      // Retrieve nickname value using User object
      psc = user.getProperties(ctx, new String[]{ nickNameAttribute });

      String nickName = null;
      try
      {
          nickName = (String) psc.getPropertySet(0).getProperty(nickNameAttribute).getValue(0);
      }
      catch (Exception e)
      {
         // unable to retrieve the attribute value
         System.exit(0);
      }
      System.out.println("Nickname : " + nickName);
   }
}

5.11 ディレクトリ・サーバーの検出

次の新しいJavaクラス(パブリック・クラス)が導入されました。

public class oracle.ldap.util.discovery.DiscoveryHelper

このクラスでは、指定されたソースから特定の情報を検出するメソッドが提供されます。

表5-1 ディレクトリ・サーバー検出のメソッド

メソッド 説明
discover

指定されたソースから特定の情報を検出します。

setProperty

検出に必要なプロパティを設定します。

getProperty

プロパティの値にアクセスします。


既存のJavaクラスoracle.ldap.util.jndi.ConnectionUtilに、次の2つの新しいメソッドが追加されます。

5.12 例: ディレクトリ・サーバーの検出

次に、ディレクトリ・サーバー検出に使用するJavaプログラムの例を示します。

import java.util.*;
import java.lang.*;
import oracle.ldap.util.discovery.*;
import oracle.ldap.util.jndi.*;

public class dsdtest
{
  public static void main(String s[]) throws Exception
  {
    HashMap reshdl = new HashMap();
    String result = new String();
    Object resultObj = new Object();
    DiscoveryHelper disco = new
DiscoveryHelper(DiscoveryHelper.DNS_DISCOVER);

// Set the property for the DNS_DN
disco.setProperty(DiscoveryHelper.DNS_DN,"dc=us,dc=fiction,dc=com")
;

// Set the property for the DNS_DISCOVER_METHOD
disco.setProperty(DiscoveryHelper.DNS_DISCOVER_METHOD,
   DiscoveryHelper.USE_INPUT_DN_METHOD);

// Set the property for the SSLMODE
disco.setProperty(DiscoveryHelper.SSLMODE,"0");

// Call the discover method
int res=disco.discover(reshdl);
if (res!=0)
   System.out.println("Error Code returned by the discover method is :"+res) ;

// Print the results
printReshdl(reshdl);
}

public static void printReshdl(HashMap reshdl)
{
  ArrayList result = (ArrayList)reshdl.get(DiscoveryHelper.DIR_SERVERS);

if (result != null)
{
  if (result.size() == 0) return;
  System.out.println("The hostnames are :-");
  for (int i = 0; i< result.size();i++)
  {
      String host = (String)result.get(i);
      System.out.println((i+1)+".
'"+host+"'");
   }
  }
 }
}

5.13 Digest-MD5を使用したSASL認証の実行

JNDIを使用してSASL接続を確立する場合、javax.naming.Contextの次のプロパティを設定する必要があります。

後者にはプリンシパル名を設定します。この名前は、サーバー固有の形式です。次のいずれかのようになります。


注意:

SASL識別名は、SASLバインドをコールするAPIに渡される前に正規化される必要があります。SASLベリファイアを生成するために、Oracle Internet Directoryでは正規化された識別名のみがサポートされます。

5.14 例: SASL Digest-MD5のauth-intモードおよびauth-confモードの使用

次のコードでは、SASL Digest-MD5を使用したJava LDAP/JNDIの例を示します。

/* $Header: LdapSasl.java 27-oct-2005.11:26:59 qdinh Exp $ */

/* Copyright (c) 2003, 2005, Oracle. All rights reserved.  */

/*
  DESCRIPTION
   <short description of component this file declares/defines>

  PRIVATE CLASSES
   <list of private classes defined - with one-line descriptions>

  NOTES
   <other useful comments, qualifications, and so on.>

  MODIFIED    (MM/DD/YY)
   qdinh       04/23/03 - Creation
*/

/**
*  @version $Header: LdapSasl.java 27-oct-2005.11:26:59 qdinh Exp $
*  @author  qdinh   *  @since   release specific (what release of product did this appear in)
*/

package oracle.ldap.util.jndi;

import javax.naming.*;
import javax.naming.directory.*;
import javax.naming.ldap.*;
import oracle.ldap.util.jndi.*;
import oracle.ldap.util.*;
import java.lang.*;
import java.util.*;
public class LdapSasl
{
   public static void main( String[] args)
       throws Exception
   {

    int numofargs;

    numofargs = args.length;

    Hashtable hashtable = new Hashtable();

    // Look through System Properties for Context Factory if it is available
    // then set the CONTEXT factory only if it has not been set
    // in the environment -
    // set default to com.sun.jndi.ldap.LdapCtxFactory

    hashtable.put(Context.INITIAL_CONTEXT_FACTORY,
          "com.sun.jndi.ldap.LdapCtxFactory");
    // possible valid arguments
    // args[0] - hostname
    // args[1] - port number
    // args[2] - Entry DN
    // args[3] - Entry Password
    // args[4] - QoP [ auth | auth-int | auth-conf ]
    // args[5] - SASL Realm
    // args[6] - Cipher Choice
    //    If QoP == "auth-conf" then args[6] cipher choice can be
    //     - des
    //     - 3des
    //     - rc4
    //     - rc4-56
    //     - rc4-40

    hashtable.put(Context.PROVIDER_URL, "ldap://"+args[0]+":"+args[1]);
        hashtable.put(Context.SECURITY_AUTHENTICATION, "DIGEST-MD5");
    System.out.println("hash put security dn: " + args[2]);
    hashtable.put(Context.SECURITY_PRINCIPAL, args[2] );
    hashtable.put(Context.SECURITY_CREDENTIALS, args[3] );

    // For Quality of Protection modes
    // 1. Authentication and Data Integrity Mode - "auth-int"
    // 2. Authentication and Data Confidentiality Mode  "auth-conf"

    //
    // hashtable.put("javax.security.sasl.qop",args[4]);
    hashtable.put("javax.naming.security.sasl.realm", args[5]);

    // Setup Quality of Protection
    //
    // System.out.println("hash sasl.qop: " + args[4]);

    hashtable.put("javax.security.sasl.qop",args[4]);


    if (numofargs > 4)
    {
    if (args[4].equalsIgnoreCase("AUTH-CONF"))
    {

        //  Setup a cipher choice only if QoP == "auth-conf"
        String strength = "high";
        String cipher = new String(args[6]);
                if (cipher.compareToIgnoreCase("rc4-40") == 0)
        strength = "low";
        else if (cipher.compareToIgnoreCase("rc4-56") == 0 ||
             cipher.compareToIgnoreCase("des")== 0 )
        strength = "medium";
        else if (cipher.compareToIgnoreCase("3des") == 0 ||
             cipher.compareToIgnoreCase("rc4") == 0)
        strength = "high";

        // setup cipher choice
        System.out.println("hash sasl.strength:"+strength);
        hashtable.put("javax.security.sasl.strength",strength);
    }

    // set maxbuffer length if necessary
    if (numofargs > 7 && !"".equals(args[6]))
        hashtable.put("javax.security.sasl.maxbuf", args[5].toString());
    }


    // Enable Debug --
    // hashtable.put("com.sun.jndi.ldap.trace.ber", System.err);

    LdapContext ctx = new InitialLdapContext(hashtable,null);


    // At this stage - SASL Digest -MD5 has been successfully

    System.out.println("sasl bind successful");

    // Ldap Search Scope Options
    //
    // - Search base - OBJECT_SCOPE
    // - One Level   - ONELEVEL_SCOPE
    // - Sub Tree    - SUBTREE_SCOPE
    //
        // Doing an LDAP Search
    PropertySetCollection psc = Util.ldapSearch(ctx,"o=oracle,dc=com","objectclass=*",SearchControls.OBJECT_SCOPE,
                           new String[] {"*"});
      // Print out the serach result
    Util.printResults(psc);

    System.exit(0);

 }                                                              }