プログラマチック・ログイン とは、 アプリケーションによる、 認証を目的としたサイト固有のログイン・フォームの表示をサポートするフォーム・ログインのことです。
エンタープライズ Bean クライアント・アプリケーションが、ユーザーに識別情報の提供を要求すると、アプリケーション の書き込み機能は、その情報を収集して、ユーザーを認証する必要があります。 プログラマーの作業は、次のように、実際のユーザー認証が実行される場合によって分類できます。
Web アプリケーションのユーザーは、 いろいろな方法で認証データの入力を求めるプロンプトを受け取ることができます。 Web アプリケーションのデプロイメント記述子ファイルにある <login-config> エレメントは、 この情報の収集に使用されるメカニズムを定義します。 ブラウザー内の 401 ダイアログ・ウィンドウなどの汎用デバイスに依存するのではなく、 ログイン手順をカスタマイズしたいプログラマーは、フォーム・ベースのログインを使用すると、 ログイン情報を収集するためのアプリケーション固有の HTML フォームを作成できます。
管理セキュリティー が使用可能になっていない場合、認証は行われません。 Web アプリケーションにフォーム・ベースのログインを使用する場合は、 各 Web アプリケーションのデプロイメント記述子内で <login-config> エレメントの auth-method タグに FORM を指定する必要があります。
アプリケーションは、WebSphere Application Server のフォーム・ログインのタイプを使用することによって、 サイト固有のログイン・フォームを表示できます。 Java 2 Platform, Enterprise Edition (J2EE) 仕様は、 Web アプリケーション用の認証方式の 1 つとして、フォーム・ログインを定義します。 WebSphere Application Server には、フォーム・ログアウトの仕組みがあります。
Java Authentication and Authorization Service (JAAS) は、 WebSphere Application Server の新しいフィーチャーです。このフィーチャーは、J2EE 1.4 仕様にも準拠したものになっています。 JAAS は、戦略的認証アプリケーション・プログラミング・インターフェース (API) の集合体で、 Common Object Request Broker Architecture (CORBA) プログラマチック・ログイン API に代わるものです。WebSphere Application Server は、JAAS に次のような拡張機能を提供します。
... import java.util.Hashtable; import javax.naming.Context; import javax.naming.InitialContext; ... // Perform an InitialContext and default lookup prior to logging // in to initialize ORB security and for the bootstrap host/port // to be determined for SecurityServer lookup. If you do not want // to validate the userid/password during the JAAS login, disable // the com.ibm.CORBA.validateBasicAuth property in the // sas.client.props file. Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.ibm.websphere.naming.WsnInitialContextFactory"); env.put(Context.PROVIDER_URL, "corbaloc:iiop:myhost.mycompany.com:2809"); Context initialContext = new InitialContext(env); Object obj = initialContext.lookup("");詳しくは、例: プログラマチック・ログイン を参照してください。
LoginContext.login API の発行後 LoginException 例外を受け取った場合、 構成済みのユーザー・レジストリーから根本原因例外を見つけることができます。ログイン・モジュールでは、 レジストリー例外は com.ibm.websphere.security.auth.WSLoginFailedException クラスでラップされています。 この例外には、前述のコマンドの発行後にラップされた例外を引き出す際に使用する getCause メソッドがあります。
常に、WSLoginFailedException 例外を受け取るとは保証されませんが、 ユーザー・レジストリーから生成された例外のほとんどはここに表示されます。 次の例は、LoginContext.login API と関連したキャッチ・ブロックを示します。 getCause API を発行する場合は、WSLoginFailedException 例外を com.ibm.websphere.security.auth.WSLoginFailedException クラスにキャストします。
try { lc.login(); } catch (LoginException le) { // drill down through the exceptions as they might cascade through the runtime Throwable root_exception = determineCause(le); // now you can use "root_exception" to compare to a particular exception type // for example, if you have implemented a CustomUserRegistry type, you would // know what to look for here. } /* Method used to drill down into the WSLoginFailedException to find the "root cause" exception */ public Throwable determineCause(Throwable e) { Throwable root_exception = e, temp_exception = null; // keep looping until there are no more embedded WSLoginFailedException or // WSSecurityException exceptions while (true) { if (e instanceof com.ibm.websphere.security.auth.WSLoginFailedException) { temp_exception = ((com.ibm.websphere.security.auth.WSLoginFailedException) e).getCause(); } else if (e instanceof com.ibm.websphere.security.WSSecurityException) { temp_exception = ((com.ibm.websphere.security.WSSecurityException) e).getCause(); } else if (e instanceof javax.naming.NamingException) // check for Ldap embedded exception { temp_exception = ((javax.naming.NamingException)e).getRootCause(); } else if (e instanceof your_custom_exception_here) { // your custom processing here, if necessary } else { // this exception is not one of the types we are looking for, // lets return now, this is the root from the WebSphere // Application Server perspective return root_exception; } if (temp_exception != null) { // we have an exception; go back and see if this has another // one embedded within it. root_exception = temp_exception; e = temp_exception; continue; } else { // we finally have the root exception from this call path, this // has to occur at some point return root_exception; } } }
Throwable t = com.ibm.websphere.security.auth.WSSubject.getRootLoginException(); if (t != null) t = determineCause(t);
例外を受け取ったら、前の determineCause の例を通じて実行し、 ネイティブ・レジストリーの根本原因を得ることができます。
現在、セキュリティー上の理由から、根本原因は純粋なクライアントには伝搬されていません。 ただし、トラステッド環境では、純 粋なクライアントに根本原因を伝搬することができます。 純粋なクライアントへの根本原因のログイン例外の伝搬を使用可能にする場合は、 WebSphere Application Server の管理コンソール上で、 「セキュリティー」>「管理、アプリケーション、インフラストラクチャーの保護 」>「 カスタム・プロパティー」の順にクリックし、以下のプロパティーを設定します。
com.ibm.websphere.security.registry.propagateExceptionsToClient=true
javax.security.auth.login.LoginContext lc = null; try { lc = new javax.security.auth.login.LoginContext("WSLogin", new com.ibm.websphere.security.auth.callback.WSCallbackHandlerImpl("user", "securityrealm", "securedpassword")); // create a LoginContext and specify a CallbackHandler implementation // CallbackHandler implementation determine how authentication data is collected // in this case, the authentication data is "push" to the authentication mechanism // implemented by the LoginModule. } catch (javax.security.auth.login.LoginException e) { System.err.println("ERROR: failed to instantiate a LoginContext and the exception: " + e.getMessage()); e.printStackTrace(); // maybe javax.security.auth.AuthPermission "createLoginContext" is not granted // to the application, or the JAAS login configuration is not defined. } if (lc != null) try { lc.login(); // perform login javax.security.auth.Subject s = lc.getSubject(); // get the authenticated subject // Invoke a J2EE resource using the authenticated subject com.ibm.websphere.security.auth.WSSubject.doAs(s, new java.security.PrivilegedAction() { public Object run() { try { bankAccount.deposit(100.00); // where bankAccount is a protected EJB } catch (Exception e) { System.out.println("ERROR: error while accessing EJB resource, exception: " + e.getMessage()); e.printStackTrace(); } return null; } } ); } catch (javax.security.auth.login.LoginException e) { System.err.println("ERROR: login failed with exception: " + e.getMessage()); e.printStackTrace(); // login failed, might want to provide relogin logic }
com.ibm.websphere.security.auth.callback.WSCallbackHandlerImpl コールバック・ハンドラーは、 純粋な Java クライアント、クライアント・アプリケーション・コンテナー、 エンタープライズ Bean、JavaServer Pages (JSP) ファイル、サーブレット、 またはその他の Java 2 Platform, Enterprise Edition (J2EE) リソースで使用できます。 純粋な Java クライアントでのオブジェクト・リクエスト・ブローカー (ORB) セキュリティーの初期設定要件について詳しくは、例: プログラマチック・ログイン を参照してください。
javax.security.auth.login.LoginContext lc = null; try { lc = new javax.security.auth.login.LoginContext("WSLogin", new com.ibm.websphere.security.auth.callback.WSGUICallbackHandlerImpl()); // create a LoginContext and specify a CallbackHandler implementation // CallbackHandler implementation determine how authentication data is collected // in this case, the authentication date is collected by GUI login prompt // and pass to the authentication mechanism implemented by the LoginModule. } catch (javax.security.auth.login.LoginException e) { System.err.println("ERROR: failed to instantiate a LoginContext and the exception: " + e.getMessage()); e.printStackTrace(); // maybe javax.security.auth.AuthPermission "createLoginContext" is not granted // to the application, or the JAAS login configuration is not defined. } if (lc != null) try { lc.login(); // perform login javax.security.auth.Subject s = lc.getSubject(); // get the authenticated subject // Invoke a J2EE resources using the authenticated subject com.ibm.websphere.security.auth.WSSubject.doAs(s, new java.security.PrivilegedAction() { public Object run() { try { bankAccount.deposit(100.00); // where bankAccount is a protected enterprise bean } catch (Exception e) { System.out.println("ERROR: error while accessing EJB resource, exception: " + e.getMessage()); e.printStackTrace(); } return null; } } ); } catch (javax.security.auth.login.LoginException e) { System.err.println("ERROR: login failed with exception: " + e.getMessage()); e.printStackTrace(); // login failed, might want to provide relogin logic }
javax.security.auth.login.LoginContext lc = null; try { lc = new javax.security.auth.login.LoginContext("WSLogin", new com.ibm.websphere.security.auth.callback.WSStdinCallbackHandlerImpl()); // create a LoginContext and specify a CallbackHandler implementation // CallbackHandler implementation determines how authentication data is collected // in this case, the authentication date is collected by stdin prompt // and passed to the authentication mechanism implemented by the LoginModule. } catch (javax.security.auth.login.LoginException e) { System.err.println("ERROR: failed to instantiate a LoginContext and the exception: " + e.getMessage()); e.printStackTrace(); // maybe javax.security.auth.AuthPermission "createLoginContext" is not granted // to the application, or the JAAS login configuration is not defined. } if (lc != null) try { lc.login(); // perform login javax.security.auth.Subject s = lc.getSubject(); // get the authenticated subject // Invoke a J2EE resource using the authenticated subject com.ibm.websphere.security.auth.WSSubject.doAs(s, new java.security.PrivilegedAction() { public Object run() { try { bankAccount.deposit(100.00); // where bankAccount is a protected enterprise bean } catch (Exception e) { System.out.println("ERROR: error while accessing EJB resource, exception: " + e.getMessage()); e.printStackTrace(); } return null; } } ); } catch (javax.security.auth.login.LoginException e) { System.err.println("ERROR: login failed with exception: " + e.getMessage()); e.printStackTrace(); // login failed, might want to provide relogin logic }