セキュリティ保護されたBankアプリケーション

この例では、安全なBankアプリケーションに種々のセキュリティサービス機能を使用します。Bankオブジェクトは、Bankレルムからのユーザのみサービスします。アカウントオブジェクトは「bankserver」識別で実行されます(これもBankレルムにあります)。アカウントデータストアは、Bankサーバが呼び出し側であることを確認します。

1 IDLのBankインタフェース

以前と同じIDLです。
module poaBank
{
    interface Account
    {
    |   exception InsufficientFunds {};
    |                                                                      
    |   float deposit(in float sum);
    |                                                                      
    |   float withdraw(in float sum) raises (InsufficientFunds);
    |                                                                      
    |   readonly attribute float balance;
    };
                                                                           
    interface Bank
    {
    |   exception noSuchAccount {};
    |                                                                      
    |   Account getAccount(in long accountNum) raises (noSuchAccount);
    };
};

2 Bankアプリケーションサーバ

Bank POAはセキュリティ機能のために追加POAポリシーで作成しされます。バンクのクライアントは「Bank」レルムで自身を認証することが必要になります。クライアントとバンクの間のメッセージは、引き続き通常のIIOP形式になります(例、IIOP/SSLではありません)。
package poaBankSecureOld;
                                                                           
import util.Util;
import org.omg.CORBA.ORB;
import org.omg.CORBA.Policy;
                                                                           
import org.omg.CosNaming.NameComponent;
import org.omg.CosNaming.NamingContext;
import org.omg.CosNaming.NamingContextHelper;
import org.omg.CosNaming.NamingContextPackage.NotFound;
                                                                           
import com.sssw.jbroker.api.PortableServer.POA;
import com.sssw.jbroker.api.security.QualityOfProtection;
                                                                           
import org.omg.PortableServer.Servant;
import org.omg.PortableServer.LifespanPolicyValue;
import org.omg.PortableServer.IdAssignmentPolicyValue;
                                                                           
import poaBank.Bank;
import poaBank.BankHelper;
                                                                           
public class Server
{
    public static void main(String[] args)
    {
    |   try {
    |   |                                                                  
    |   |   // create the jBroker ORB
    |   |   ORB orb = ORB.init(args, null);
    |   |                                                                  
    |   |   // get the root POA
    |   |   POA rootPOA = (POA) orb.resolve_initial_references("RootPOA");
    |   |                                                                  
    |   |   // create a persistent user assigned ids POA
    |   |   POA bankPOA = (POA) rootPOA.create_POA("bankPOA",
    |   |       rootPOA.the_POAManager(),
    |   |       new Policy[] {
    |   |       |   rootPOA.create_id_assignment_policy(
    |   |       |       IdAssignmentPolicyValue.USER_ID),
    |   |       |   rootPOA.create_lifespan_policy(
    |   |       |       LifespanPolicyValue.PERSISTENT),
    |   |       |   rootPOA.create_security_policy("bank")
    |   |       });
    |   |                                                                  
    |   |   // create and activate bank servant
    |   |   Servant bank = new BankImpl(orb, bankPOA, args[0]);
    |   |   bankPOA.activate_object_with_id("bank".getBytes(), bank);
    |   |                                                                  
    |   |   // get the root of the NameService
    |   |   NamingContext root = NamingContextHelper.narrow(
    |   |       orb.resolve_initial_references("NameService"));
    |   |                                                                  
    |   |   // if not done before, publish the bank objref
    |   |   NameComponent nc = new NameComponent("secureBankOld", "");
    |   |   NameComponent[] name = new NameComponent[] { nc };
    |   |   try {
    |   |   |   root.resolve(name);
    |   |   } catch (NotFound ex) {
    |   |   |   // create the bank objref
    |   |   |   Bank bankObj = BankHelper.narrow(bankPOA.
    |   |   |       create_reference_with_id("bank".getBytes(),
    |   |   |           bank._all_interfaces(null, null)[0]));
    |   |   |                                                              
    |   |   |   System.out.println(orb.object_to_string(bankObj));
    |   |   |   root.rebind(name, bankObj);
    |   |   }
    |   |                                                                  
    |   |   // activate bankPOA
    |   |   bankPOA.the_POAManager().activate();
    |   |                                                                  
    |   |   // wait for invocations
    |   |   System.out.println("waiting for invocations ...");
    |   |   orb.run();
    |   |                                                                  
    |   } catch (Exception ex) {
    |   |   ex.printStackTrace();
    |   }
    }
}

3 Bankの実装

Bankの実装はほぼ以前と同じです。呼び出し側のIPアドレスを表示するためのSecurity Currentは取得します。IPアドレスベースのアクセス制御を実行するために、使用された可能性があります。
package poaBankSecureOld;
                                                                           
import java.io.File;
                                                                           
import org.omg.CORBA.ORB;
import org.omg.CORBA.Policy;
                                                                           
import org.omg.PortableServer.POA;
import org.omg.PortableServer.Servant;
import org.omg.PortableServer.POAPackage.WrongPolicy;
import org.omg.PortableServer.IdUniquenessPolicyValue;
import org.omg.PortableServer.IdAssignmentPolicyValue;
import org.omg.PortableServer.ServantRetentionPolicyValue;
import org.omg.PortableServer.RequestProcessingPolicyValue;
                                                                           
import com.sssw.jbroker.api.security.SecurityCurrent;
                                                                           
import poaBank.BankPOA;
import poaBank.Account;
import poaBank.AccountHelper;
import poaBank.BankPackage.noSuchAccount;
                                                                           public class BankImpl extends BankPOA
{
    ORB                    _orb;
    POA                    _acctPOA;
    String                 _acctRepId; // repository Id for Account Objects
    Servant                _defaultServant;
    SecurityCurrent        _securityCurrent;
                                                                           
    BankImpl(ORB orb, POA bankPOA, String dir) throws Exception
    {
    |   _orb = orb;
    |                                                                      
    |   // make sure that the DB dir exists
    |   File dbDir = new File (dir);
    |   if (!dbDir.exists()) dbDir.mkdir();
    |                                                                      
    |   // get the securtity current
    |   _securityCurrent = (SecurityCurrent) _orb.resolve_initial_references(
    |       "SecurityCurrent");
    |                                                                      
    |   // create the POA for Transient Account Objects
    |   _acctPOA = bankPOA.create_POA("acctPOA", bankPOA.the_POAManager(),
    |       new Policy[] {
    |       |   bankPOA.create_id_assignment_policy(
    |       |       IdAssignmentPolicyValue.USER_ID),
    |       |   bankPOA.create_request_processing_policy(
    |       |       RequestProcessingPolicyValue.USE_DEFAULT_SERVANT),
    |       |   bankPOA.create_id_uniqueness_policy(
    |       |       IdUniquenessPolicyValue.MULTIPLE_ID)
    |       });
    |                                                                      
    |   // set the servant manager in Acct POA
    |   _defaultServant = new AccountImpl(_orb, dbDir);
    |   _acctPOA.set_servant(_defaultServant);
    |                                                                      
    |   // compute the repository id for Account objects
    |   _acctRepId = _defaultServant._all_interfaces(null, null)[0];
    }
                                                                           
    public Account getAccount(int acctNum) throws noSuchAccount
    {
    |   Account account = null;
    |                                                                      
    |   // print out the IP Address of the caller
    |   System.out.println(_securityCurrent.getInetAddress());
    |                                                                      
    |   if ((acctNum >= 100) && (acctNum < 110)) {
    |   |                                                                  
    |   |   // construct the object id for account
    |   |   byte objectId[] = new byte[1];
    |   |   objectId[0] = (byte) (acctNum & 0xFF);
    |   |                                                                  
    |   |   try {
    |   |   |   account = AccountHelper.narrow(_acctPOA.
    |   |   |      create_reference_with_id(objectId, _acctRepId));
    |   |   } catch (WrongPolicy ex) { // remove on JDK1.4
    |   |   |   ex.printStackTrace();
    |   |   }
    |   }
    |                                                                      
    |   if (account == null) throw new noSuchAccount();
    |                                                                      
    |   return account;
    }
}

4 Accountの実装

アカウントのデフォルトサーバントが作成されると、それ自身で「bankserver」として認証され、アカウントデータストアでgetAccountメソッドを呼び出すときにその識別が常に使用されます。stackThreadPrincipalunstackThreadPrincipalの使用に注意してください。

この例では、アカウントデータストアがローカルのJavaオブジェクトです。アカウントデータストアがリモートオブジェクトである場合(別の場所で実行されている可能性があります)、識別「bankserver」がそれに伝播されます。

AuthenticatedPrincipalはSerializableであり、AccountImplでは安全な場所から読み込んだばかりである可能性があるため注意してください。

package poaBankSecureOld;
                                                                           
import java.io.File;
                                                                           
import org.omg.CORBA.ORB;
import org.omg.CORBA.INTERNAL;
import org.omg.CORBA.INITIALIZE;
import org.omg.CORBA.PERSIST_STORE;
                                                                           
import poaBank.AccountPOA;
import poaBank.AccountPackage.InsufficientFunds;
                                                                           
import com.sssw.jbroker.api.security.Authenticator;
import com.sssw.jbroker.api.security.SecurityCurrent;
import com.sssw.jbroker.api.security.SecurityException;
import com.sssw.jbroker.api.security.AuthenticationScheme;
import com.sssw.jbroker.api.security.AuthenticatedPrincipal;
                                                                           
public class AccountImpl extends AccountPOA
{
    ORB                    _orb;
    AccountBalances        _accountsDb;
    SecurityCurrent        _securityCurrent;
    AuthenticatedPrincipal _principal;
                                                                           
    public AccountImpl(ORB orb, File acctDb) throws Exception
    {
    |   _orb        = orb;
    |                                                                      
    |   // authenticate with the bank realm
    |   Authenticator authenticator = (Authenticator) _orb.
    |       resolve_initial_references("Authenticator");
    |   _principal = authenticator.authenticate(AuthenticationScheme.DIGEST,
    |       "bank", "bankserver", "manager".getBytes());
    |                                                                      
    |   // get the Security current
    |   _securityCurrent = (SecurityCurrent) _orb.resolve_initial_references(
    |       "SecurityCurrent");
    |                                                                      
    |   // create the account Db
    |   _accountsDb = new AccountBalances(acctDb, _securityCurrent);
    }
                                                                           
    private AccountRecord getAccount(int acctNum)
    {
    |   try {
    |   |   try {
    |   |   |   _securityCurrent.stackThreadPrincipal(_principal);
    |   |   |   return _accountsDb.getAccount(acctNum);
    |   |   } finally {
    |   |   |   _securityCurrent.unstackThreadPrincipal(_principal);
    |   |   }
    |   } catch (SecurityException ex) {
    |   |   ex.printStackTrace();
    |   |   throw new INTERNAL();
    |   }
    }
                                                                           
    public float deposit(float sum)
    {
    |   int acctNum = getAccountNumber();
    |                                                                      
    |   AccountRecord record = getAccount(acctNum);
    |                                                                      
    |   float balance = 0;
    |   synchronized (record) {
    |   |   balance = record.getBalance() + sum;
    |   |   record.setBalance(balance);
    |   }
    |                                                                      
    |   return balance;
    }
                                                                           
    public float withdraw(float sum) throws InsufficientFunds
    {
    |   int acctNum = getAccountNumber();
    |                                                                      
    |   AccountRecord record = getAccount(acctNum);
    |                                                                      
    |   float balance = 0;
    |   synchronized (record) {
    |   |   balance = record.getBalance();
    |   |   if ((balance - sum) < 0)
    |   |       throw new InsufficientFunds();
    |   |   balance -= sum;
    |   |   record.setBalance(balance);
    |   }
    |                                                                      
    |   return balance;
    }
                                                                           
    public float balance()
    {
    |   return getAccount(getAccountNumber()).getBalance();
    }
                                                                           
    private int getAccountNumber()
    {
    |   return _object_id()[0] & 0x000000FF;
    }
}

5 アカウントDataStore

5.1 Account Balances

getAccountメソッドは、呼び出し側が「Bank」レルムの「bankserver」であることをチェックします。
package poaBankSecureOld;
                                                                           
import java.io.File;
import java.util.Hashtable;
                                                                           
import org.omg.CORBA.NO_PERMISSION;
                                                                           
import com.sssw.jbroker.api.security.SecurityCurrent;
import com.sssw.jbroker.api.security.SecurityException;
import com.sssw.jbroker.api.security.AuthenticatedPrincipal;
                                                                           
// Datastore for Account Balances
class AccountBalances
{
    File            _dbDir;
    Hashtable       _table;
    SecurityCurrent _current;
                                                                           
    AccountBalances(File dbDir, SecurityCurrent current)
    {
    |   _dbDir   = dbDir;
    |   _table   = new Hashtable(19);
    |   _current = current;
    }
                                                                           
    synchronized AccountRecord getAccount(int acctNum)
    {
    |   // verify the caller is bank server
    |   if (!_current.getPrincipal().getName().equals("bankserver@bank"))
    |       throw new NO_PERMISSION();
    |                                                                      
    |   Integer AcctNum = new Integer(acctNum);
    |                                                                      
    |   AccountRecord record = (AccountRecord) _table.get(AcctNum);
    |                                                                      
    |   if (record == null) {
    |   |   record = new AccountRecord(0, new File(_dbDir,
    |   |       AcctNum.toString()));
    |   |   _table.put(AcctNum, record);
    |   }
    |                                                                      
    |   return record;
    }
}

5.2 Account Record

package poaBankSecureOld;
                                                                           
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
                                                                           
import org.omg.CORBA.PERSIST_STORE;
                                                                           
class AccountRecord
{
    private float _balance;
    private File  _file;
                                                                           
    AccountRecord(float balance, File file)
    {
    |   _file    = file;
    |   _balance = balance;
    |                                                                      
    |   // if file exists read balance
    |   if (_file.exists()) {
    |   |   try {
    |   |   |   FileInputStream fis = new FileInputStream(_file);
    |   |   |   ObjectInputStream ois = new ObjectInputStream(fis);
    |   |   |   _balance = ((Float) ois.readObject()).floatValue();
    |   |   |   ois.close();
    |   |   } catch (Exception ex) {
    |   |   |   throw new PERSIST_STORE();
    |   |   }
    |   }
    }
                                                                           
    float getBalance()
    {
    |   return _balance;
    }
                                                                           
    void setBalance(float balance)
    {
    |   _balance = balance;
    |                                                                      
    |   try {
    |   |   FileOutputStream fos = new FileOutputStream(_file);
    |   |   ObjectOutputStream oos = new ObjectOutputStream(fos);
    |   |   oos.writeObject(new Float(_balance));
    |   |   oos.close();
    |   } catch (Exception ex) {
    |   |   throw new PERSIST_STORE();
    |   }
    }
}

6 サーバの登録

サーバ展開記述子。
server.main=poaBankSecureOld.Server
server.alias=secureBankOld
server.classpath=/usr/local/JBroker/examples/lib
server.args=/usr/local/JBroker/examples/src/poaBankSecureOld/db
server.vmflags=-DORBUseDoors=true

7 Bankクライアント

認証部分以外に、クライアントコードの残りの部分は以前と同じです。

クライアントはユーザから取得したアカウント番号およびPINを使用して自身を認証し、ORBレベルで認証されたプリンシパルを設定します。クライアントが複数のスレッドを開始している場合、同じ識別ですべて実行されていることになります。

package poaBankSecureOld;
                                                                           
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
                                                                           
import org.omg.CORBA.ORB;
                                                                           
import org.omg.CosNaming.NameComponent;
import org.omg.CosNaming.NamingContext;
import org.omg.CosNaming.NamingContextHelper;
                                                                           
import com.sssw.jbroker.api.security.Authenticator;
import com.sssw.jbroker.api.security.SecurityCurrent;
import com.sssw.jbroker.api.security.AuthenticationScheme;
import com.sssw.jbroker.api.security.AuthenticatedPrincipal;
                                                                           
import poaBank.Bank;
import poaBank.Account;
import poaBank.BankHelper;
import poaBank.AccountPackage.InsufficientFunds;
                                                                           
public class Client
{
    ORB     _orb;
    Bank    _bank;
    Account _account;
    String  _acctNum;
    String  _acctPIN;
                                                                           
    public static void main(String[] args)
    {
    |   try {
    |   |   new Client().run(args);
    |   } catch (Exception ex) {
    |   |   ex.printStackTrace();
    |   }
    }
                                                                           
    public void run(String[] args) throws Exception
    {
    |   // create the jBroker ORB
    |   _orb = ORB.init(args, null);
    |                                                                      
    |   // get the root of the NameService
    |   NamingContext root = NamingContextHelper.narrow(
    |       _orb.resolve_initial_references("NameService"));
    |                                                                      
    |   // get the bank object reference
    |   NameComponent nc = new NameComponent(args[0], "");
    |   NameComponent[] name = new NameComponent[] { nc };
    |   _bank = BankHelper.narrow(root.resolve(name));
    |                                                                      
    |   // enter the request processing loop
    |   processCommands();
    }
                                                                           
    void processCommands() throws Exception
    {
    |   // create a input stream reader
    |   BufferedReader reader = new BufferedReader(new InputStreamReader(
    |       System.in));
    |                                                                      
    |   // get the account number
    |   System.out.print("Enter Account number: ");
    |   System.out.flush();
    |   _acctNum = reader.readLine();
    |                                                                      
    |   // get the account PIN
    |   System.out.print("Enter Account PIN: ");
    |   System.out.flush();
    |   _acctPIN = reader.readLine();
    |                                                                      
    |   // authenticate with the bank realm
    |   Authenticator authenticator = (Authenticator) _orb.
    |       resolve_initial_references("Authenticator");
    |   AuthenticatedPrincipal principal = authenticator.authenticate(
    |       AuthenticationScheme.DIGEST, "bank", _acctNum, _acctPIN.getBytes());
    |                                                                      
    |   // set the authenticated principal at the ORB level
    |   SecurityCurrent current = (SecurityCurrent) _orb.
    |       resolve_initial_references("SecurityCurrent");
    |   current.setORBPrincipal(principal);
    |                                                                      
    |   // get the account object
    |   _account = _bank.getAccount(new Integer(_acctNum).intValue());
    |                                                                      
    |   // enter the read-execute loop
    |   while (true) {
    |   |   System.out.print("bank > ");
    |   |   executeCommand(readCommandLine(reader));
    |   }
    }
                                                                           
    void executeCommand(String[] command) throws Exception
    {
    |   if (command.length == 0)
    |       printHelp();
    |                                                                      
    |   // get balance
    |   else if (command[0].equals("b"))
    |       System.out.println("\tbalance: $" + _account.balance());
    |                                                                      
    |   // check the command for addition parameter
    |   else if (command[0].equals("d")) {
    |   |   if (command.length != 2) printHelp();
    |   |   else System.out.println("\tbalance: $"+ _account.deposit(new Float(
    |   |       command[1]).floatValue()));
    |   }
    |                                                                      
    |   // deposit money
    |   else if (command[0].equals("w")) {
    |   |   if (command.length != 2) printHelp();
    |   |   else {
    |   |   |   try {
    |   |   |   |   System.out.println("\tbalance: $"+ _account.withdraw(
    |   |   |   |       new Float(command[1]).floatValue()));
    |   |   |   } catch (InsufficientFunds ex) {
    |   |   |   |   System.out.println("\tInsufficient Funds!");
    |   |   |   }
    |   |   }
    |   }
    |                                                                      
    |   // quit
    |   else if (command[0].equals("q")) {
    |   |   System.exit(0);
    |   }
    |                                                                      
    |   // print help
    |   else printHelp();
    }
                                                                           
    void printHelp()
    {
    |   System.out.println();
    |   System.out.println("\tCommands:");
    |   System.out.println("\t   b               // get balance");
    |   System.out.println("\t   d <sum>         // deposit sum");
    |   System.out.println("\t   w <sum>         // withdraw sum");
    |   System.out.println("\t   q               // quit");
    |   System.out.println();
    }
                                                                           
    String[] readCommandLine(BufferedReader reader) throws Exception
    {
    |   int i=0;
    |                                                                      
    |   String line = reader.readLine();
    |                                                                      
    |   if (line == null) System.exit(0);
    |                                                                      
    |   StringTokenizer tokenizer = new StringTokenizer(line);
    |   String[] command = new String[tokenizer.countTokens()];
    |   while (tokenizer.hasMoreTokens()) {
    |   |   command[i++] = tokenizer.nextToken();
    |   }
    |                                                                      
    |   return command;
    }
}
Copyright © 2000-2003, Novell, Inc.All rights reserved.