13.10.2 セッションフェイルオーバ機能使用時のユーザ認証の実装

セッションフェイルオーバ機能使用時のログインとログアウトの実装方法,および実装時の注意点について説明します。

<この項の構成>
(1) APIを使用する場合
(2) タグライブラリを使用する場合
(3) シングルサインオンを使用する場合の注意

(1) APIを使用する場合

セッションフェイルオーバ機能では,String型以外のオブジェクトは引き継げません。したがって,ユーザ属性(UserAttributes)を引き継ぐには,必要な文字情報を取り出して,グローバルセッション情報に格納する必要があります。

ここでは,セッションフェイルオーバ機能使用時のユーザ認証の実装例を示します。

(a) ログイン(セッションフェイルオーバ機能使用時)

ログインでは,ログインが成功したときのユーザIDと必要なユーザ情報をグローバルセッションに登録しておきます。

<%
 LoginContext lc = new LoginContext("Example",
   new WebPasswordHandler(request, response, null, "login.html", true));
 try {
   lc.login();
   Subject subject = lc.getSubject();
   session.setAttribute("ExampleSubject", subject);   // SubjectをHttpSessionに格納
   String uid = ((Principal)subject.getPrincipals().iterator().next()).getName();
   session.setAttribute("ExampleUserID", uid);   //ユーザIDをグローバルセッションに格納します。
   UserAttributes attr = (UserAttributes)lc.getSubject().getPublicCredentials().iterator().next();
   session.setAttribute("telephoneNumber", attr.getAttribute("tel"));
                                                      //電話番号をグローバルセッションに格納します。
 } catch (LoginException e) { ... }
%>

ユーザIDはSFOサーバの障害発生時に備えて,読み取り専用で登録することを推奨します。

(b) ログアウト(セッションフェイルオーバ機能使用時)

ログアウトは,ログイン時に取得したSubjectとグローバルセッションに登録されているユーザIDとHttpSessionを使って行います。ただし,フェイルオーバが発生したあとは,Subjectオブジェクトがnullになっているので,新たにSubjectを生成して指定してください。

<%
 try {
   String uid = (String)session.getAttribute("ExampleUserID");//グローバルセッションからユーザIDを取得
   Subject subject = (Subject)session.getAttribute("ExampleSubject");
   LoginContext lc = new LoginContext("Example",
     (subject != null) ? subject : new Subject(), //Subjectがnullの場合は,新規にSubjectを生成します。
     new WebLogoutHandler(session, uid));         //WebLogoutHandlerをLoginContextに設定します。
   session.removeAttribute("ExampleUserID");
   lc.logout();
 } catch (LoginException e) { ... }
%>

(c) セッションタイムアウト時のログアウト(セッションフェイルオーバ機能使用時)

セッションタイムアウト時にログアウトするためには,HttpSessionBindingListenerインタフェースを実装したオブジェクトをHttpSessionオブジェクトに設定します。ただし,フェイルオーバ発生後は,HttpSessionが新しく生成されるので登録したオブジェクトはなくなります。画面遷移などのタイミングでオブジェクトがなくなっていないか確認し,なくなっていれば再登録する必要があります。

<%
 LoginContext lc = new LoginContext("Portal",
   new WebPasswordHandler(request, response, null, "login.html", true));
 try {
   lc.login();
   Subject subject = lc.getSubject();
   String uid = ((Principal)subject.getPrincipals().iterator().next()).getName();
   session.setAttribute("PortalSubject", subject);   // SubjectをHttpSessionに格納
   session.setAttribute("PortalUserID", uid);   // ユーザIDをグローバルセッションに格納します。
   session.setAttribute("myLogoutObject",       // セッションタイムアウト時にログアウト処理を
     new MyListener("Portal", "PortalUserID", "PortalSubject")); //行うオブジェクトをHttpSessionに設定。
 } catch (LoginException e) { ... }
%>
<%!
 class MyListener implements                              // セッションタイムアウト時に
     HttpSessionBindingListener, java.io.Serializable {   // ログアウト処理を行うクラス。
   String name;
   String userName;
   String subjectName;
   public MyListener(String name, String userName, String subjectName) {
     this.name = name;
     this.userName = userName;
     this. subjectName = subjectName;
   }
   public void valueBound(HttpSessionBindingEvent ev) {}
   public void valueUnbound(HttpSessionBindingEvent ev) {
     String uid = (String)ev.getSession().getAttribute(userName);
     Subject subject = (Subject)ev.getSession().getAttribute(subjectName);
     try {
       LoginContext ctx = new LoginContext(name,
         (subject != null) ? subject : new Subject(),
         new WebLogoutHandler(ev.getSession(), uid));
       ctx.logout();
     } catch (LoginException e) { ... }
   }
 }
%>

(d) ログイン状態のチェック(セッションフェイルオーバ機能使用時)

フェイルオーバが発生した場合,ログアウトするために登録したHttpSessionBindingListenerインタフェースの実装したオブジェクトがなくなっています。したがって,オブジェクトがないか確認し,なくなっていれば再登録する必要があります。

<%!
 if (LoginUtil.check(request, response)) {
   HttpSession session = request.getSession();
   if (session.getAttribute("myLogoutObject") == null) {
     session.setAttribute("myLogoutObject",
         new MyListener("Portal", session.getAttribute("userid"), "PortalSubject");
   }
 } else {
   //ログインしていない場合の処理
 }
%>

(2) タグライブラリを使用する場合

セッションフェイルオーバ機能使用時は,ユーザ属性(UserAttributes)が引き継げないため,次のタグの使用が制限されます。

<ua:getAttributes/>
id属性を指定した場合は,スクリプト変数にnullを代入します。id属性を指定していない場合は,何もしません。
<ua:getAttribute/>
id属性を指定した場合は,スクリプト変数にnullを代入します。id属性を指定していない場合は,何もしません。
<ua:getAttributeNames/>
id属性を指定した場合は,スクリプト変数にnullを代入します。id属性を指定していない場合は,何もしません。

ユーザ属性(UserAttributes)を引き継ぐには,必要な文字情報を取り出して,グローバルセッション情報に格納する必要があります。

(3) シングルサインオンを使用する場合の注意

同一レルムおよび同一ユーザで多重ログインするような処理にしないでください。多重ログインが発生した場合,シングルサインオンが正しく機能しない場合があります。