ヘッダーをスキップ

Oracle WebCenter Framework WebCenterアプリケーションの構築 - ステップ・バイ・ステップ
10g(10.1.3.2.0)

E05617-02
目次
目次
索引
索引

戻る 次へ

6 ログイン・ページの作成

この章では、ユーザーが認証のためにリダイレクトされるログイン・ページを新規作成します。通常、WebCenterアプリケーションにはパブリック・ページの概念があり、明示的な認証も暗黙的な認証も可能です。つまり、ユーザーは、ログイン・リンクをクリックしてアプリケーションにログインしてから保護コンテンツに移動する(明示的)、あるいは保護ページに移動するとアプリケーションのログイン・ページにリダイレクトされる(暗黙的)ことが可能です。暗黙的および明示的な認証の詳細は、『Oracle WebCenter Framework開発者ガイド』の「WebCenterアプリケーションの保護」を参照してください。図6-1に、この章で構築するサンプルのログイン・ページを示します。

図6-1    SRDemoアプリケーションのログイン・ページ


画像の説明

SRDemoSample_Starterアプリケーションには、すでにログイン・ページSRLogin.jspxが含まれています。このページは、図6-2に示す場所にあります。

図6-2    元のSRDemoログイン・ページ


画像の説明

ログイン・ページではログイン・フォームを使用するので、通常、ADF Facesページはログイン・ページに使用しません。これは、ADF Facesライフサイクルがログイン・フォームの送信アクションおよびフォームのフィールドを内部参照に再マップして、ログイン機能を中断するためです。しかし、ログイン・ページはアプリケーションの重要な部分です。このページには、ポートレットやデータ・コントロールなどのカスタマイズ可能な情報を含めることができます。また、ADF Facesページで使用できるスキニング機能を利用することも可能です。また、ログイン・ポートレットを実装してもかまいません。この章では、SRDemoアプリケーション用にADF Facesベースのログイン・ページを構築する方法について学びます。このログイン・ページのフォームでは、J2EEセキュリティ・コンテナ・ログイン・メソッドj_security_checkも使用します。この章の内容は次のとおりです。

手順1: ログイン・ページの作成

ADF Facesベースのログイン・ページを作成するには、次の手順を実行します。

  1. アプリケーション・ナビゲータで、必要に応じて、「UserInterface」プロジェクトの「Webコンテンツ」フォルダを開きます。

  2. 「infrastructure」フォルダ(図6-2)を右クリックし、「新規」を選択します。

  3. 「新規ギャラリ」ダイアログ・ボックスで、「Web Tier」ノードを開きます。

  4. 「JSF」を選択します。

  5. 「項目」リストで、「JSF JSP」を選択します。

  6. 「OK」をクリックして「JSF JSPの作成」ダイアログ・ボックスを表示します。

  7. ウィザードの「ようこそ」ページが表示されたら、「次へ」をクリックして「JSPファイル」ページを表示します。

  8. 「ファイル名」フィールドに、SRLoginADF.jspxと入力します。

  9. 「JSPドキュメント(*.jspx)」を選択します。

  10. 「次へ」をクリックして「コンポーネント・バインディング」ページを表示します。

  11. 「新規マネージドBeanでのUIコンポーネントの自動公開」を選択します。

  12. 「次へ」をクリックして「タグ・ライブラリ」ページを表示し、「すべてのライブラリ」を選択します。

  13. 次のライブラリが「選択済のライブラリ」に表示されていることを確認します。

    • JSF Core

    • JSF HTML

    • ADF Faces Components

    • ADF Faces HTML

    • ADF Portlet Components

    • Customizable Components Core

  14. 「終了」をクリックしてページを作成します。

  15. ページを保存します。

  16. SRLoginADF.jspxページの「ソース」ビューで、例6-1に示すコードをコピーし、f:viewタグの直前に貼り付けます。

    例6-1    SRDemoリソース・バンドルへの参照

    <!-- Resource Bundle for Translatable Strings within Application =========== -->
    <f:loadBundle basename="oracle.srdemo.view.resources.UIResources" var="res"/>
    
  17. ファイルを保存します。

  18. 「設計」ビューに切り替えます。

  19. コンポーネント・パレットから、「ADF Faces Core」を選択します。

  20. 「PanelPage」コンポーネントを選択して「構造」ペインのbody要素の上にドラッグします。要求されても、フォームを追加しないでください。これは、後で独自のフォームを追加してデフォルトのフォーム要素を削除するためです。

  21. Titleプロパティを変更し、アプリケーションに付属するリソース・バンドルの文字列にバインドします。プロパティ・インスペクタで、「Title」をクリックします。

  22. 「データにバインド」アイコン(プロパティ・インスペクタの上部にあるデータベース・アイコン)をクリックします。「データにバインド」ダイアログ・ボックスが表示されます。

  23. 「JSP objects」「res」を選択し、srlogin.pageTitle変数を探します。

  24. この変数を「式」フィールドに移動して、「OK」をクリックします。

  25. ページ・タイトル・キーsrlogin.pageTitleにファセットをいくつか追加します。そのためには、例6-2に示す既存のブランド・ファセット・コードを探します。

    例6-2    元のブランド・ファセット

    <f:facet name="branding"/>
    
  26. このブランド・イメージ・ファセット・コードを例6-3に示すファセット・コードで置き換えます。これにより、ブランド・ファセット内のロゴ・イメージに、選択したスキンの適切な企業ブランド・ロゴが反映されます。

    例6-3    新しいブランド・ファセット

    <!-- Site Branding Section (Top Left of Page) ============================== -->
          <f:facet name="branding">
                <af:objectImage 
    source="/skins/#{skinBean.currentSkin}/skin_images/SRBranding.gif"/>
          </f:facet>
    
  27. 次に、コピーライト・ファセットを新しいログイン・ページに追加します。SRLoginADF.jspxページで、例6-4に示す既存のコピーライト・ファセット・コードを探します。

    例6-4    元のコピーライト・ファセット

    <f:facet name="appCopyright"/>
    
  28. このコピーライト・ファセットを例6-5に示すファセットで置き換えます。これにより、スキンBeanからブランド・イメージがロードされるため、スキンを変更すると、実行時にブランド・イメージも必ず変更されます。

    例6-5    コピーライト・ファセット

    <!-- Copyright Message -->
         <f:facet name="appCopyright">
           <h:panelGroup>
             <af:outputText value="#{res['srdemo.copyright']}"/>
             <af:objectSpacer width="10" height="10"/>
           </h:panelGroup>
         </f:facet>
    
  29. ログイン・ページをADF Facesページとして作成したので、コンポーネント・パレットのフォーム要素を使用してログイン・フォームを追加するわけにはいきません。その操作は、ADF Facesライフサイクルによってフォーム要素が実行時にシリアライズされ、再マップされる原因となります。かわりに、アクティブなJSFコンポーネント(Facesライフサイクルに送信されて戻ってくる)を囲むフォームにログイン・コンポーネントが依存しないようにページを設計します。これはJSFページ内のタグをそのまま使用することで実現できますが、非常に複雑になり、利用できる柔軟性は制限されます。ログイン・コンポーネントを(一連のエスケープされたHTMLタグではなく)ページをあちこち移動したり簡単にスキン化できる単一要素として処理できるようにするために、HTMLフォームをユーザー・インタフェースと切り離し、実行時に動的に挿入することができます。これは、HTMLフォームをバッキングBeanに組み込み、返されたHTMLをユーザー・インタフェースにレンダリングされるOutputTextオブジェクトに公開することで実現できます。そのためには、次の手順を実行します。


    注意

    コードは、(ルート・ディレクトリの)開始時にダウンロードしたZIPファイルに含まれるSRLoginADF_Backing_Code.txtファイルから入手できます。 


    1. 「backing」「infrastructure」フォルダ内にあるバッキングBeanのSRLoginADF.java図6-3を参照)を開き、HTML挿入コードをバッキングBeanに追加して実行時にページに挿入されるようにします。このコードは原則として、該当するHTMLをページに直接生成します。そのため、様々なgetterメソッドが適切にマークアップされたHTMLを単純な文字列として返します。この動的に生成されたHTMLを使用するメリットは、スキン情報への参照を組み込むことができることです。FacesページへのHTMLの統合は、ページ内のタグおよびCDATAエスケープをそのまま使用しないことで簡略化されます。

      図6-3    アプリケーション・ナビゲータでのSRLoginADF.javaの場所


      画像の説明

    2. 今度は、Javaコードをファイルに追加します。そのためには、例6-6に示すimport文を追加します。

      例6-6    import文

      import javax.faces.application.FacesMessage;
      import javax.faces.context.FacesContext;
      import javax.servlet.http.HttpSession;
      import oracle.adf.share.ADFContext;
      import oracle.adf.view.faces.component.core.output.CoreMessages;
      import oracle.srdemo.view.util.JSFUtils;
      
    3. バッキングBeanのプロパティをSRLoginADF.javaの先頭に追加します(例6-7を参照)。これらのプロパティのgetterメソッドは、後でログイン・ページの式言語で参照されます。

      例6-7    バッキングBeanのプロパティ

      private String  _loginStyleBlock   = null;
      private String  _loginScriptBlock  = null;
      private String  _loginFormBlock    = null;
      private boolean _validLoginAttempt = true;
      

      表6-1に、これらのプロパティの説明を示します。

      表6-1    SRLoginADF.javaファイルのバッキングBeanのプロパティ 
      変数  説明 

      loginStyleBlock 

      CSSクラスを定義するためのHTMLが含まれます。 

      loginScriptBlock 

      ログイン・フォームで使用される必須JavaScriptのHTMLが含まれます。 

      loginFormBlock 

      ログイン・フォーム自体のHTMLが含まれます。 

      validLoginAttempt 

      現行ユーザーがもう一度ログインを試行できるかどうかを示すブール値。ユーザーが有効なログイン試行回数を超過した場合、falseに設定されます。 

    4. getloginStyleBlock getterメソッドをバッキングBeanに挿入します。例6-8を参照してください。

      このメソッドは、認証プロセスが実行中であることを示すために、ログイン・フォームで使用されるフラッシュ・テキストを定義する単純なスタイルシートを生成します。このメソッドによって生成されるHTMLは表示できないため、ページの本体の外側に出力文字列をレンダリングできます。

      例6-8    getloginStyleBlock getterメソッド

      /**
        * ============================================================================
        * Function to generate the CSS style class referenced in Login Form
        * ============================================================================
        * @return
        */
      public String getloginStyleBlock()
      {
        _loginStyleBlock = "\n\n"
                         + "<!-- 
      ========= CSS Style Block Generated in Backing Bean ========= -->\n"
                         + "<style type=\"text/css\">\n"
                         + ".VP_Blink {text-decoration: blink;}\n"
                         + "</style>\n"
                         + "<!--
       ============================================================= -->"
                         + "\n\n";
        return (_loginStyleBlock);
      }
      
    5. getloginScriptBlock getterメソッドをバッキングBeanに挿入します。例6-9を参照してください。

      このメソッドは、ログイン・フォームで使用されるJavaScript関数を含む<script>ブロックを生成します。これらの関数には、フィールド検証アクションやフォーム送信アクションがあります。JavaScriptは動的に生成されるため、現行スキンへの参照の他にリソース・バンドルの適切な文字列を組み込むことができます。たとえば、現行スキンがmyCompanyに設定されている場合、次の行は、JavaScriptのアラート・メッセージをリソース・バンドル・キーに定義されている値(SRLoginADF.myCompany.jsAlert)になるように設定します。

      String alertMsg    = JSFUtils.getStringFromBundle("SRLoginADF." +
      currentSkin + ".jsAlert");
      

      同様に、このメソッドは、認証中であることを示す適切なアイコンを特定し、Faces外部コンテキストに基づいてそのアイコンへのURLを生成します。

      例6-9    getloginScriptBlock getterメソッド

      /**
       * ============================================================================
       * Method getloginScriptBlock() to generate a JScript Submit form block.
       * This function implements the current skin and generates simple JavaScript
       * to validation the user input prior to the Authentication submit action.
       * ============================================================================
       * @return
       */
      public String getloginScriptBlock()
      {
       String currentSkin = (String)
       JSFUtils.getManagedBeanValue("skinBean.currentSkin");
       String alertMsg    = JSFUtils.getStringFromBundle("SRLoginADF." 
                                                         + currentSkin + 
                                                         ".jsAlert");
       String valPwdMsg   = JSFUtils.getStringFromBundle("SRLoginADF." 
                                                         + currentSkin + 
                                                         ".AuthMsg");
       String urlBaseRef  =
      FacesContext.getCurrentInstance().getCurrentInstance().getExternalContext().getRequestC
      ontextPath();
       String processIcon = urlBaseRef + "/skins/" + currentSkin + 
      "/skin_images/process_animation.gif";
           
       _loginScriptBlock = "\n\n"
                         + "<!-- 
      ======== JavaScript Block Generated in Backing Bean ========= -->\n"
                         + "<SCRIPT language=\"JavaScript\" type=\"text/JavaScript\">\n"
                         + "(new Image(32,32)).src=\"" + processIcon +"\";\n"
                         + "function SubmitForm(AuthFrm){\n"
                         + "var alertMsg =\""   + alertMsg  + "\";\n"
                         + "var valPwdMsg = \"" + valPwdMsg + "\";\n\n"
                         + "if (((AuthFrm.j_username.value == null) || 
      (AuthFrm.j_username.value ==\"\")) ||\n"
                         + "    ((AuthFrm.j_password.value == null) || 
      (AuthFrm.j_password.value ==\"\")))\n"
                         + " {\n  alert(alertMsg);\n  return false;\n }\n else\n {\n"
                         + " var divTag = document.getElementById(\"vp\");\n"
                         + " divTag.innerHTML = '<table width=\"50\" border=\"0\"><tr>' +\n"
                         + "                    '<td align=\"center\"><img src=\"" 
                                                 + processIcon + "\" width=\"32\"
                                                 height=\"32\"></td>' +\n"
                         + "                    '<td align=\"left\"><font size=\"-2\"
                                                 class=\"VP_Blink\">' + valPwdMsg +
                                                 '</font></td>' +\n"
                         + "                    '</tr></table>';\n"
                         + " return true;\n"
                         + " }\n}\n"
                         + "</SCRIPT>\n"
                         + "<!--
       ============================================================= -->"
                         + "\n\n";
      return (_loginScriptBlock);
      }
      
    6. getLoginFormBlock getterメソッドをバッキングBeanに挿入します。例6-10を参照してください。

      このメソッドは、ページ内にレンダリングされるHTMLログイン・フォームを定義する文字列を生成します。HTMLは動的であるため、現行スキンへの参照の他にリソース・バンドルのキーも組み込むことができます。さらに、ログイン・ページはログイン後にカスタマイズできるように設計されているため、ADFセキュリティ・コンテキストのisAuthenticated();メソッドを使用してHTMLのdisabledプロパティが動的に設定されるので、HTMLはユーザーの認証状態を敏感に反映します。

      その場合、ユーザーが認証されてログイン・ページがアクセスされると、ログイン・ページは(レンダリング時に)非アクティブ化されてそれ以降のログイン試行はできなくなります。たとえば、サイト管理ページからページがアクセスされる場合
      第9章「サイト管理ページの構築」を参照)がこれに該当します。

      次の例では、ADFセキュリティ・コンテキストのisAuthenticatedの状態に基づいて、文字列変数htmlDisable"disabled="true""またはnullのいずれかになることがわかります。

      String htmlDisable 
      =(ADFContext.getCurrent().getSecurityContext().isAuthenticated() ? 
      "disabled=\"true\"" : null);
      

      次のコードは、その後で、入力フィールドや「送信」ボタンなどのフォーム要素をアクティブ化または無効化するために、htmlDisable文字列を使用する方法を示しています。

      <input type=\"text\" name=\"j_username\" "+ htmlDisable + "/></td>\n"
      
      

      例6-10    getLoginFormBlock getterメソッド

      /**
       * ===========================================================================
       * Method getLoginFormBlock() generates the standard Credential Form used
       * by container security. The function implements the current skin values and
       * returns the required HTML which is subsequently output using an OutputText
       * object populated using EL. While this could also have been achieved by 
       * directly using the Verbatim tags within the JSPX itself, this would require the
       * use of CDATA escapes and complicates the design of the page (the login form
       * is exposed through a faces component in this case.)
       *
       * Note as the Login Page contains customizable components, the HTML form elements
       * generated are disabled if the user is currently authenticated.
       * ==========================================================================
       * @return
       */
      
      public String getLoginFormBlock()
      {
        String currentSkin       = (String)
      JSFUtils.getManagedBeanValue("skinBean.currentSkin");
        String userNameLabel     = JSFUtils.getStringFromBundle("SRLoginADF." 
                                                                + currentSkin +
                                                                ".userName");
        String passwordLabel     = JSFUtils.getStringFromBundle("SRLoginADF." 
                                                                + currentSkin +
                                                                ".password");
        String submitButtonLabel = JSFUtils.getStringFromBundle("SRLoginADF." +
                                                                 currentSkin +
                                                                ".buttonLabel");
        String htmlDisable       =
      (ADFContext.getCurrent().getSecurityContext().isAuthenticated() ? "disabled=\"true\"" : 
      null);
           
        _loginFormBlock = "\n\n"
                        + "<!-- 
      ======== Login Form Block Generated in Backing Bean ========= -->\n"
                        + "<form name=\"LoginForm\" id=\"LoginForm\" \n"
                        + " action=\"j_security_check\" method=\"POST\"
                            onSubmit=\"return SubmitForm(this)\" >\n"
                        + "<table cellspacing=\"5\" cellpadding=\"0\" border=\"0\"
                           width=\"50%\" bgcolor=\"#FFFFFF\" width=\"240\" >\n"
                        + " <tr>\n"
                        + "  <td nowrap>" + userNameLabel + "</td>\n"
                        + "  <td nowrap><input type=\"text\" name=\"j_username\" 
                          "  + htmlDisable + "/></td>\n"
                        + " </tr>\n"
                        + " <tr>\n"
                        + "  <td nowrap>" + passwordLabel + "</td>\n"
                        + "  <td nowrap><input type=\"password\" name=\"j_password\" 
                          " + htmlDisable + "/></td>\n"
                        + " </tr>\n"
                        + " <tr>\n"
                        + "  <td nowrap height=\"34\"><DIV id=\"vp\"></DIV></td>\n"
                        + "  <td nowrap>\n"
                        + "    <input type=\"submit\" value=\"" + submitButtonLabel + 
                          "\" " + htmlDisable + "/></td>\n"
                        + "  </td>\n"
                        + " </tr>\n"
                        + "</table>\n"
                        + "</form>\n"
                        + "<!--
       ============================================================= -->"
                        + "\n\n" ;
        return ( _loginFormBlock);
      }
      
    7. ファイルを保存します。

  30. コンポーネント・パレットから、「ADF Faces Core」を選択します。

  31. 「PanelHorizontal」を選択してpageコンポーネントの上にドラッグします。

  32. プロパティ・インスペクタでValignプロパティをmiddleに設定します。

  33. ADF Faces Coreコンポーネント・パレットから「ObjectImage」を選択してPanelHorizontalコンポーネントの上にドラッグします。source属性を次の値に設定します。

    /skins/#{skinBean.currentSkin}/skin_images/LoginSplash.gif
    
  34. 「ObjectSpacer」を選択してObjectImageコンポーネントのすぐ下のpageの上にドラッグします。

  35. コンポーネント・パレットから、「カスタマイズ可能コンポーネント・コア」を選択します。

  36. 「PanelCustomizable」を選択し、「構造」ペインで追加したばかりのObjectSpacer要素の下にドラッグします。要求されても、フォームを追加しないでください。これは、後で独自のフォームを追加してデフォルトのフォーム要素を削除するためです。

  37. PanelCustomizableコンポーネントのLayoutプロパティをverticalに設定します。

  38. コンポーネント・パレットから、「ADF Faces Core」を選択します。

  39. 今度は、次のものをPanelCustomizableコンポーネントに追加します。

    • objectSpacerを1つ

    • objectSeparatorを1つ

    • objectSpacerを1つ

    • panelHorizontalを1つ

      Halignプロパティをcenterに設定します。

    • objectSpacerを1つ

    • objectSeparatorを1つ

    • objectSpacerを1つ

  40. 「PanelBox」を選択してPanelHorizontalコンポーネントの上にドラッグします。

  41. 式言語(EL)を使用して、PanelBoxTextプロパティを、リソース・バンドルを参照することでログイン・コンポーネント・ヘッダーになるように設定します。そのためには、「データにバインド」アイコンをクリックします。「データにバインド」ダイアログ・ボックスが表示されます。

  42. 「JSP objects」「res」を選択し、SRLoginADF.credentialHeader変数を探します。

  43. ADF Faces Coreコンポーネント・パレットから「OutputText」を選択してPanelBoxコンポーネントの上にドラッグします。

  44. プロパティ・インスペクタで、「JSF Managed Beans」「backing_infrastructure_SRLoginADF」「loginFormBlock」の順に選択して、OutputTextコンポーネントのValueプロパティをマネージドBeanのデータにバインドします(図6-4を参照)。

    図6-4    データへのバインド


    画像の説明

  45. OutputTextコンポーネントのEscapeプロパティをfalseに設定します。

  46. 別のOutputTextコンポーネントを「構造」ペインのbodyタグの上(ページの先頭のすぐ下)にドラッグします(図6-5を参照)。

    図6-5    「構造」ペイン


    画像の説明

  47. 「JSF Managed Beans」「backing_infrastructure_SRLoginADF」「loginStyleBlock」の順に選択してValueプロパティをバッキングBeanのデータにバインドし、Escapeプロパティをfalseに設定します。

  48. 別のOutputTextコンポーネントを、「構造」ペインのbodyタグのすぐ上にドラッグします。

  49. 「JSF Managed Beans」「backing_infrastructure_SRLoginADF」「loginScriptBlock」の順に選択してValueプロパティをバッキングBeanのデータにバインドし、Escapeプロパティをfalseに設定します。

  50. SRLoginADF.jspxページの「構造」ペインで、「panelPag」ノードを開き、Messagesコンポーネントをmessagesファセットの上にドラッグします。

  51. ファイルを保存します。

手順2: ログイン・エラー・ページの作成

ログイン・エラー・ページを作成するには、次の手順を実行します。

  1. アプリケーション・ナビゲータで、必要に応じて、「UserInterface」プロジェクトの「Webコンテンツ」ノードを開きます。

  2. 「infrastructure」フォルダ(図6-2)を右クリックし、「新規」を選択します。

  3. 「新規ギャラリ」ダイアログ・ボックスで、「Web Tier」ノードを開きます。

  4. 「JSP」を選択します。

  5. 「項目」リストで、「JSP」を選択します。

  6. 「OK」をクリックして「JSPの作成」ダイアログ・ボックスを表示します。

  7. ウィザードの「ようこそ」ページが表示されたら、「次へ」をクリックして「JSPの作成」ページを表示します。

  8. 「ファイル名」フィールドに、SRLoginErrorPage.jspと入力します。

  9. ウィザードの「エラー・ページ・オプション」ページで、「このファイルの捕捉されない例外の処理にエラー・ページを使用しない」を選択します。

  10. 「タグ・ライブラリ」ページで、「すべてのライブラリ」を選択し、「JSTL Core 1.1」を選択して「選択済のライブラリ」リストに移動します。

  11. 「終了」をクリックします。

  12. 例6-11に示すJSTLコードを<html>要素の直前に追加して、ログイン試行回数を追跡管理します。

    例6-11    ログイン試行回数を追跡管理するためのJSTLコード

    <!-- ===========================================================================
     For the SRDemo Demo we will track the number of Login Attempts against the file 
     based repository (In a deployed system this would be handled by the IdM system).
     This counter is then used in the backing bean to define if the login attempt
     is valid (referenced in EL as "loginAttemptValid").
     =========================================================================== -->
    <c:set var="LoginErrorCount" 
           scope="session" 
           value="${sessionScope.LoginErrorCount == null ? 1 :sessionScope.LoginErrorCount 
    + 1}"/>
    <c:redirect url="/faces/infrastructure/SRLoginADF.jspx"/>
    

    このJSTLコードにより、(無効なログインによって)エラー・ページがコールされた回数が単純なセッション変数に格納され、ユーザーは実際の処理が行われている元のログイン・ページにリダイレクトされます。

  13. SRLoginErrorPage.jsp ファイルを保存します。

  14. バッキングBeanの「SRLoginADF.java」を開き、例6-12に示すgetMessages1()メソッドを追加します。

    次の2つのメソッドでは、Faces外部コンテキストを使用してエラー・ページでJSTLによって設定されたセッション変数を返し、ユーザーがログインを試行した回数を特定します。

    次のコードは、Facesコンテキストおよび関連付けられたHTTPセッションに基づいてセッション変数を返す方法を示しています。返されたオブジェクトは、ユーザーのログイン試行回数が有効か否かを評価するために、ローカル整数に変換されます。たとえば、試行回数上限3回は次のように適用できます。

    FacesContext facesContext = FacesContext.getCurrentInstance();
    HttpSession  session = 
    (HttpSession)facesContext.getExternalContext().getSession(true);
    Object loginAttempts  = session.getAttribute("LoginErrorCount");
    Integer loginAttemptCount = (loginAttempts == null)? 0 : 
    Integer.parseInt(loginAttempts.toString());
    


    注意

    getMessages1メソッドは、PanelPageのmessageコンポーネント用に作成されるデフォルトのgetterメソッドです。messageコンポーネントがmessages1ではない場合、メソッドの名前を変更する必要があります。

    現在のログイン試行回数が特定されると、getMessages1メソッドは、(リソース・バンドルから返される)適切なエラー文字列をFacesのmessageコンポーネントに設定します。その場合、2回以上の試行は無効なユーザー名とパスワードの組合せを示し、4回以上の試行はユーザーが適正な上限を超過したことを示します。 


    例6-12    getMessage1()メソッド

    /**
         * ===========================================================================
         * Function getMessages1() determines the current number of login failures and
         * sets the appropriate error message in the Faces Context
         * ===========================================================================
         * @return
         */
        public CoreMessages getMessages1()
        {
         if (!ADFContext.getCurrent().getSecurityContext().isAuthenticated())
         {
           String       currentSkin       = (String)
           JSFUtils.getManagedBeanValue("skinBean.currentSkin");
           FacesContext facesContext      = FacesContext.getCurrentInstance();
           HttpSession  session           = (HttpSession)
           facesContext.getExternalContext().getSession(true);
           Object       loginAttempts     = session.getAttribute("LoginErrorCount");
           Integer      loginAttemptCount = (loginAttempts == null)? 0 :
           Integer.parseInt(loginAttempts.toString());
           String       loginErrorMessage = null;
           if (loginAttemptCount >0)
           {
            if (loginAttemptCount >2) {
             loginErrorMessage = JSFUtils.getStringFromBundle(
                                 "SRLoginADF." + currentSkin +
                                 ".tooManyLoginAttempts");
            }
            else {
             loginErrorMessage = JSFUtils.getStringFromBundle(
                        "SRLoginADF." + currentSkin + ".invalidLogin");
            }
            FacesMessage fm =  new FacesMessage(
                       FacesMessage.SEVERITY_INFO,loginErrorMessage,null);
            facesContext.addMessage(null, fm );
           }
         }
         return messages1;
        }
    
  15. バッキングBeanの「SRLoginADF.java」を開き、例6-13に示すisValidLoginAttemptメソッドを追加します。

    isValidLoginAttemptメソッドから返されるブール値は、ログイン・フォームのHTMLコードが含まれるoutputtextコンポーネントのrenderedプロパティで参照されます。その場合、有効な試行回数が3回を超えるとき、ログイン・フォームはページにレンダリングされず、ユーザーは再度ログインすることができなくなります。

    例6-13    isValidLoginAttemptメソッド

        /**
         * ===========================================================================
         * Method isValidLoginAttempt() evaluates the number of invalid login attempts
         * performed by the user and returns false if greater than 3. (used in EL to
         * show/hide the Login Page components.
         * ===========================================================================
         * @return
         */
        public boolean isValidLoginAttempt()
        {
          _validLoginAttempt = true;
          if (!ADFContext.getCurrent().getSecurityContext().isAuthenticated()) {
             FacesContext facesContext      = FacesContext.getCurrentInstance();
             HttpSession  session           = (HttpSession)
             facesContext.getExternalContext().getSession(true);
             Object       loginAttempts     = session.getAttribute("LoginErrorCount");
             Integer      loginAttemptCount = (loginAttempts == null)? 0 
            : Integer.parseInt(loginAttempts.toString());
                 
             if (loginAttemptCount >2){ _validLoginAttempt = false; }
          }
          return (_validLoginAttempt);
        }
    
  • ファイルを保存します。

  • 「SRLoginADF.jspx」を開きます。

  • ObjectImageOutputTextオブジェクトの下のPanelBoxにドラッグし、sourceプロパティを次の値に設定します。

    source="/skins/#{skinBean.currentSkin}/skin_images/BadLoginAttempt.gif"
    
  • renderedプロパティをバッキングBeanのisValidLoginAttempt()メソッドの否定(反対)値にバインドします。renderedプロパティを次の値に設定します。

    #{!backing_infrastructure_SRLoginADF.validLoginAttempt}
    

    この設定により、イメージはログイン試行が無効の場合のみレンダリングされます。

  • OutputTextオブジェクトのrenderedプロパティを、次のようなisValidLoginAttempt()メソッドの値に設定します。

    #{backing_infrastructure_SRLoginADF.validLoginAttempt}
    

    これで、ログイン・フォームはユーザーのログイン試行が有効な場合のみレンダリングされます。

    手順3: ログイン・ページへのリッチ・テキスト・ポートレットの追加

    この項では、リッチ・テキスト・ポートレットをログイン・ページに追加します。そのためには、次の手順を実行します。

    1. 作業を進める前に、リッチ・テキスト・ポートレットが登録されていることを確認します。詳細は、第5章「パブリックなようこそページの作成」「手順1: リッチ・テキスト・コンポーネントの追加」を参照してください。

    2. コンポーネント・パレットから、「RichTextPortletProducer」を選択し、リストから「リッチ・テキスト」を選択します。「構造」ペインで、このリッチ・テキスト・ポートレットpanelCustomizable内の先頭のobjectSpacerの上にドラッグします。

    3. リッチ・テキスト・ポートレットを選択し、プロパティ・インスペクタを開きます。

    4. 次のプロパティを設定します。

      プロパティ   

      AllModesSharedScreen 

      true 

      IsMinimizable 

      false 

      IsMaximizable 

      false 

      DisplayHeader 

      false 

    5. コンポーネント・パレットから、「RichTextPortletProducer」を選択し、リストから「リッチ・テキスト」を選択します。「構造」ペインで、このリッチ・テキスト・ポートレットpanelCustomizable内の最後のobjectSpacerの下にドラッグします。

    6. リッチ・テキスト・ポートレットを選択し、プロパティ・インスペクタを開きます。

    7. 次のプロパティを設定します。

      プロパティ   

      AllModesSharedScreen 

      true 

      IsMinimizable 

      false 

      IsMaximizable 

      false 

      DisplayHeader 

      false 

    8. ページを保存します。

    これで、ログイン後にログイン・ページに戻って、このリッチ・テキスト・ポートレットをカスタマイズできます。その実現方法は、第9章「サイト管理ページの構築」を参照してください。

    手順4: ログイン・ページ用の認可の編集

    次に、適切な権限をログイン・ページに定義する必要があります。すべてのユーザーがページを表示できる必要があります。また、管理者は、リッチ・テキスト・ポートレットを更新できるように、ページの編集もできる必要があります。ログイン・ページにセキュリティを設定するには、次の手順を実行します。

    1. アプリケーション・ナビゲータで、「SRLoginADF.jspx」を右クリックします。

    2. 「ページ定義に移動」を選択します。

    3. ページ定義を新規作成するように要求された場合は、「はい」をクリックします。「構造」ペインでページ定義ファイルが開きます。

    4. 「Page Definition」ファイルを右クリックし、「認可の編集」を選択します。認可エディタが表示されます。

    5. View権限をanyoneに、Edit権限をmanagerに付与します(図6-6を参照)。

      図6-6    ログイン・ページにセキュリティを定義するための認可エディタ


      画像の説明

    手順5: ADFセキュリティおよびログイン・ページを使用するためのアプリケーションの構成

    この手順では、Oracle ADFセキュリティ・ウィザードを使用してSRDemoアプリケーションの認証設定を構成します。選択したオプションはすべてweb.xmlに記録されます。認証設定を構成するには、次の構成作業を実行する必要があります。

    ADFセキュリティおよびログイン・ページを使用するようにSRDemoアプリケーションを構成するには、次の手順を実行します。

    1. アプリケーション・ナビゲータで、「UserInterface」を開きます。

    2. 「ツール」メニューから、「ADFセキュリティ・ウィザード」を選択します。ADFセキュリティ・ウィザードにより、構成プロセスを誘導されます。

    3. 必要に応じて、「次へ」をクリックして「ようこそ」ページをスキップします。

    4. 「強制認可」が選択されていることを確認します。このオプションにより、adfAuthenticationサーブレットが構成され、認可ルール(ページに対する現行ユーザーの権限をチェックできる適切なフィルタ)が構成されます。

    5. 「次へ」をクリックしてウィザードの次のページに移動します。

    6. 「軽量XMLプロバイダ」を選択します。Oracle ADFセキュリティでは、特定のリソース・プロバイダに対してユーザーを認証します。SRDemoの場合、ダウンロードしたサンプル・ファイルに含まれるinstall.htmlファイルの手順に従ってコピーした、軽量リソース・プロバイダのsystem-jazn-data.xmlを使用します。

    7. 「次へ」をクリックしてウィザードの次のページを表示します。

    8. このページで、「場所」に「アプリケーション・リポジトリ」、「デフォルト・レルム」にjazn.com、「JAASモード」にdoAsPrivilegedと設定し、「次へ」をクリックします。

    9. 「ログイン」ページで、「フォームベース認証」を選択します(図6-7)。これにより、SRDemoアプリケーションではフォームを使用して認証が円滑に行われます。

      ログイン・フォームおよびログイン・エラー・メッセージ(login.htmlおよびerror.html)用にデフォルトのページを生成する必要はありません。これは、SRLoginADF.jspx内にすでに構築したログイン・フォームを使用するためです。

    10. 「ログイン・ページ」フィールドに、faces/infrastructure/SRLoginADF.jspxと入力します。

    11. また、「エラー・ページ」フィールドに、faces/infrastructure/SRLoginErrorPage.jspと入力できます(図6-7を参照)。

      図6-7    フォームベース認証の詳細


      画像の説明

    12. 「次へ」をクリックしてウィザードの最後のページを表示します。

      このページは、保護対象となるアプリケーション内のリソースを定義し、各リソースにアクセスできるJ2EEセキュリティ・ロールを指定します。adfAuthenticationリソース(認証サーブレット)が定義されています。このリソースは、編集または削除できませんが、このリソースにアクセスできる一連のロールを指定できます。デフォルトでJ2EEロールが1つ(oc4j-administrators)選択されていますが、adfAuthenticationリソースには任意の有効なユーザーがアクセスできるようにする必要があるため、ValidUserという名前のJ2EEロールを別に作成し、このロールにアクセス権を付与する必要があります。

    13. WebリソースのJ2EE-Secured-Applicationが表示されている場合は、これを削除します。

    14. 「ロールの管理」をクリックします。

    15. 「追加」をクリックし、名前のValidUserを入力します。

      後で、このJ2EEロールをIDストアのロールの1つusersにマップします。これは、このレッスンの始めに定義したロールです。このロールは、すべての有効なユーザーのリストを保持しています。セキュリティの観点から、このロールに権限を割り当てると、認証されたパブリック・リソースが事実上定義されます。つまり、特定の権限を定義する必要なしにすべてのユーザーが使用できるようになります。

    16. 「OK」をクリックします。ValidUserロールがリストに表示されます。

    17. 「閉じる」をクリックします。

    18. 二重矢印(「すべて追加」)をクリックし、「使用可能なロール」リストのロールをすべて「選択したロール」リストに移動します。

    19. ADFセキュリティ・ウィザードの設定はこれで完了したので、「次へ」をクリックし、「終了」をクリックします。

    20. これで、アプリケーションのSRWelcome.jspxページを実行でき、パブリックにアクセスできるようこそページが表示されます。

    21. 「login」リンクをクリックします。この章で構築したログイン・ページが表示されます。

    22. 管理者(sking)としてログインします。RTPのコンテンツは、通常、サイト管理ページに定義されます。このページは後で構築します。


      注意

      サイト管理を作成する前に、ページに対してCustomize権限を持つユーザーとしてページURLに直接アクセスすると、ログイン・ページをカスタマイズできます。 


    手順6: 新しいログイン・ページをコールするためのWeb.xmlの更新

    新しいログイン・ページをコールするようにweb.xmlを更新する手順は、次のとおりです。

    1. アプリケーション・ナビゲータで、「WEB-INF」ノードを開き、「web.xml」プロパティ・パレットを開きます(ポップアップ・メニューから「プロパティ」を選択します)。

    2. 左側のパネルで「フィルタ・マッピング」を選択し、新しいフィルタ・マッピングをadfBindingsフィルタに追加します(図6-8を参照)。

      図6-8    adfBindingsフィルタに対する新しいフィルタ・マッピング


      画像の説明

      必ず、「サーブレット名」にFaces Servletと入力し、「フォワード」および「インクルード」の各ディスパッチャ・タイプを選択します。

    3. 「OK」をクリックしてweb.xmlへの変更内容を保存します。


      注意

      ログイン・ページはJSPXページでもある(よってADFセキュリティによって保護されている)ため、パブリック・ページとして定義する必要があります。ページがパブリックとして定義されないと、コンテナは、このページへのアクセスを許可するまでずっと定義された認証ポイントにリダイレクトします(当然、このページは何度も繰り返されます)。 


    4. アプリケーション・ナビゲータで、「SRLoginADF.jspx」ページを右クリックし、「ページ定義に移動」を選択します。ページ定義ファイルが現在存在しない場合は、そのファイルの作成を確認します。

    5. ページ定義ファイルを右クリックし、「認可の編集」を選択します。

    6. View権限をanyoneロールに付与します(図6-9を参照)。

      図6-9    認可エディタ


      画像の説明

    7. ログイン・ページには、カスタマイズ可能なポートレットが含まれているため、該当するロールにはページに対するCustomize権限が必要です。

    手順7: アプリケーションの実行

    これで、アプリケーションを実行し、作成したログイン・ページとエラー・ページが正しく表示されるかどうかをテストできます。そのためには、次の手順を実行します。

    1. SRWelcome.jspxページを実行します。

    2. 「login」リンクをクリックします。ログイン・ページが表示されます。

    3. 有効なユーザー名およびパスワードを使用してログインします。

      デモ・アプリケーションに正常にログインします。

    4. アプリケーションからログアウトします。

    5. エラー・ページが正しく表示されるかどうかをテストするには、間違った資格証明を3回使用してログインします。エラー・ページが表示されます。

    まとめ

    この章では、ADF Facesベースのログイン・ページを構築し、そのログイン・ページを使用するようにSRDemoアプリケーションを構成する方法について学びました。この時点で、管理者が実行時にログイン・ページをカスタマイズできるようにすることができます。この種のカスタマイズを可能にする手順は、第9章「サイト管理ページの構築」を参照してください。


  • 戻る 次へ
    Oracle
    Copyright © 2007 Oracle Corporation.

    All Rights Reserved.
    目次
    目次
    索引
    索引