WebLogic Server 12c上のJava EE 6 Webアプリケーションのユーザー認証および認可

概要

    目的

    このチュートリアルでは、フォームベースの認証とロールベースの認可を使用してJava EE 6 Webアプリケーションを保護する方法について説明します。 具体的には、ユーザー・データとパスワード・データの収集クライアントとしてJavaServer Facesを使用したログイン・フォームの作成方法と、サーブレットにアクセスする特定のロールの認可方法を示します。

    また、WebLogic Server 12cにユーザーを追加し、認証および認可プロセスで使用されるWebアプリケーション・ロールにマッピングする方法も示します。

    所要時間

    約60分

    はじめに

    Webアプリケーションのリソースには、何らかのアクセス制限を必要とするものがあります。 企業の多くは、Webアプリケーションの全体または一部を保護し、特定のユーザー/ロールにのみアクセスを許可するよう求めています。

    ユーザーまたはエンティティのIDを検証するには、認証プロセスを使用します。 認証は、実際のユーザーと入力されたユーザーが一致することを確認するプロセスです。 また、ユーザーが操作の実行権限やデータへのアクセス権限を持つことを確認するには、認可プロセスを使用します。

    保護されたリソースへのアクセスをWebクライアントが要求すると、ユーザー名とパスワードなどの認証データに基づいて、Webサーバーに対するWebクライアントの初期認証が行われます。 Webサーバーによるデータの検証が成功すると、Webサーバーは要求されたコンテンツを呼出し元のWebページに送信することで、最初の要求に応じます。 それ以外の場合は、"not authorized"というエラー・メッセージがWebクライアントに返されます。

    Java EEでは、コンポーネント・コンテナがアプリケーション・セキュリティの提供責任を負います。 コンテナは、宣言的セキュリティとプログラム的セキュリティの2種類を提供しています。 宣言的セキュリティはデプロイメント・ディスクリプタまたは注釈を使用して実装され、プログラム的セキュリティはアプリケーションに組み込まれています。

    このチュートリアルでは、2種類のセキュリティの両方を実装します。 ログイン・フォームの開発中にデプロイメント・ディスクリプタを作成することで、宣言的セキュリティを使用したセキュリティ制約を指定します。 また、request.loginメソッドとrequest.logoutメソッドをプログラムで使用したマネージドBeanで、プログラム的セキュリティを使用してログイン・プロセスを管理します。 また、呼出し元のIDをプログラムでチェックします。 チュートリアルの最後では、宣言的セキュリティに戻り、注釈を使用してサーブレットへのアクセスを特定のロールに限定します。

    宣言的セキュリティだけではアプリケーションのセキュリティ・モデルを十分に実装できない場合、プログラム的セキュリティが有効です。 このチュートリアルでは、HttpServletRequestのインタフェース・メソッドを使用します。 これらのメソッドを使用すると、あらかじめWebLogic Serverレルムに登録された呼出し元のセキュリティ・ロールに基づいて、ビジネス・ロジックの決定を下すことができます。

    シナリオ

    このチュートリアルでは、以下を実行します。

    • WebLogic Serverへのユーザーの追加
    • セキュリティ制約の指定
    • ログイン・フォームの作成
    • ログイン・フォームの制御用マネージドBeanの作成
    • 注釈を使用したサーブレットへのアクセスの保護

    前提条件

    このチュートリアルを始める前に以下のことを確認してください。

    • こちらのリンクからJava JDK 7をダウンロードし、インストールしていること。
    • こちらのリンクからNetBeans IDE 7.2をダウンロードし、インストールしていること。
    • こちらのOBEのはじめの3項を完了して、WebLogic Server 12cのzip配布ファイルをダウンロードおよびインストールし、NetBeansで構成していること。

WebLogic Serverへのユーザーの追加

    ここでは、WebLogic Serverレルムにユーザーを追加します。 次の項で、これらのユーザーを認証および認可します。

    NetBeansを起動します。 Servicesウィンドウを開きます(Window」→「Services)。

    Servers 」フォルダを開きます。

    Oracle WebLogic Server」を右クリックします。 「Start」をクリックします。

    Oracle WebLogic Server」を右クリックします。 「View Admin Console」をクリックします。

    Admin Consoleでユーザー名にweblogicを、パスワードにwelcome1を入力します (使用している管理アカウントのユーザー名とパスワードが上記と異なる場合は、適切な値を入力します)。

    Login」をクリックします。

    左側のペインで「Security Realms」を選択します。

    Summary of Security Realmsページで「myrealm」を選択します。

    WebLogic Serverに含まれているmyrealmは、このチュートリアルでユーザー管理用に使用する組込みLDAPサーバーです。 JDBC認証レルムを構成し、myrealmの代わりに使用することもできます。

    Settings for myrealmページで「Users and Groups」タブをクリックします。

    Users表には、WebLogic Serverレルムに現在登録されているユーザーが表示されます。

    New」をクリックします。

    Nameにwebuserと入力します。

    Passwordに「welcome2」と入力します。

    もう一度、Confirm Passwordに「welcome2」と入力します。

    OK」をクリックします。

    Descriptionフィールドは省略可能です。

    もう一度「New」をクリックします。 今回は管理ユーザーを作成します。

    Nameにwebadminと入力します。

    Passwordに「welcome3」と入力します。

    もう一度、Confirm Passwordに「welcome3」と入力します。

    OK」をクリックします。



    以上で、WebLogic Serverインスタンスでのwebuserwebadminのユーザー登録が完了しました。

Webプロジェクトでのセキュリティ制約の指定

    ここでは、新規Webプロジェクトを作成し、web.xmlファイルとweblogic.xmlファイルにセキュリティ制約を追加します。

    Java Webプロジェクトの作成

      NetBeansで「File」→「New Project」の順に選択します。

      Categoriesから「Java Web」を選択し、Projectsから「Web Application」を選択します。Next」をクリックします。

      Project NameにSecureDukeRealmと入力します。

      Project LocationにD:\NetBeansProjectsまたはNetBeansプロジェクトを保存するフォルダ・パスを指定します。

      Next」をクリックします。

      ServerとしてOracle WebLogic Serverが選択されていることを確認します。

      Java EE VersionがJava EE 6 Webになっていることを確認します。

      Enable Contexts and Dependency Injection」チェック・ボックスを選択します。

      Set Source Level to 6」チェック・ボックスのデフォルト選択を解除します。

      Next」をクリックします。

      Frameworksで「JavaServer Faces」を選択します。 「Finish」をクリックします。

      NetBeansによってプロジェクト内にSecureDukeRealmというWebプロジェクトが作成され、index.xhtmlファイルにエントリ・ポイントが作成されます。 次の項では、web.xmlファイルとweblogic.xmlファイルに制約を追加することで、このファイルを保護します。

    セキュリティ制約の指定

      ここでは、web.xmlファイル内にWebアプリケーションのセキュリティ制約を指定します。 ここはデプロイメント・ディスクリプタを作成するため、宣言的セキュリティを使用します。 また、weblogic.xmlファイルにエントリを追加して、WebLogic Serverレルムに作成したユーザーをWebアプリケーションのロールにマッピングします。

      プロジェクトのWEB-INFフォルダにあるweb.xmlファイルに、次のコードを追加します。

           <security-constraint>
              <display-name>Protected Area</display-name>
              <web-resource-collection>
                  <web-resource-name>Protected Area</web-resource-name>
                  <description/>
                  <url-pattern>/*</url-pattern>
              </web-resource-collection>
              <auth-constraint>
                  <description/>
                  <role-name>User</role-name>
              </auth-constraint>
           </security-constraint>
           <login-config>
              <auth-method>FORM</auth-method>
              <realm-name>myrealm</realm-name>
              <form-login-config>
                  <form-login-page>/faces/login.xhtml</form-login-page>
                  <form-error-page>/faces/login.xhtml</form-error-page>
              </form-login-config>
          </login-config>
           <security-role>
              <description/>
              <role-name>User</role-name>
          </security-role>
          <security-role>
              <description/>
              <role-name>Admin</role-name>
          </security-role>


      XMLコードの説明

      <security-constraint><web-resource-collection><url-pattern>タグの内部に/*を入力することで、Webアプリケーションに含まれるすべての要素へのアクセスが制約されます。 <url-pattern>タグを使用すると、Webリソースへの完全アクセスや部分アクセスを許可できます。


      <auth-constraint><role-name>タグでは、保護された領域(Webアプリケーション全体)へのアクセスをUserロールに対して認可します。


      また、WebアプリケーションがFORM認証タイプを使用していることを<login-config><auth-method>タグに指定し、使用するレルムがmyrealmであることを<realm-name>タグに指定します。


      ログイン・ページとエラー・ページを<form-login-config>タグに定義します。


      <security-role><role-name>タグに、UserAdminという2つのロールを定義します。


      次の項では、weblogic.xmlファイルを使用してWebLogic Serverに作成したユーザーに対して、これら2つのロールを関連付けます。

      プロジェクトのWEB-INFフォルダにあるweblogic.xmlファイルに次のコードを追加します。

         <security-role-assignment>
              <role-name>User</role-name>
              <principal-name>webadmin</principal-name>
              <principal-name>webuser</principal-name>
          </security-role-assignment>
          <security-role-assignment>
              <role-name>Admin</role-name>
              <principal-name>webadmin</principal-name>
          </security-role-assignment>

      ここでは、WebLogic Serverレルムに定義したwebadminwebuserという2つのユーザーが、web.xmlファイルでWebアプリケーションに対して定義したUserロールとAdminロールにマッピングされています。

      <principal-name>タグでは、Webアプリケーションに1つずつユーザーを登録しなくても済むよう、グループを定義することもできます。

      図1に、Webアプリケーションのロールと、それぞれのロールに対応するWebLogic Serverユーザーを示します。

      図1: SecureDukeRealmアプリケーションのロール。 このチュートリアルの最後の項で、Adminロールのみがサーブレットにアクセスできるようにする方法を示します。

ログイン・フォームの作成と管理

    ここではログイン・ページを作成し、そのログイン・ページを管理するマネージドBeanを作成します。

    ログイン・ページの作成

      プロジェクトを右クリックします。New」→「Other」を選択します。

      Categoriesから「Java Server Faces」を選択し、File Typesとして「JSF Page」を選択します。 「Next」をクリックします。

      File Nameに「login」と入力します。

      Finish」をクリックします。

      NetBeansによって、プロジェクトのWeb Pagesフォルダにlogin.xhtmlというFaceletが作成されます。

      login.xhtmlファイルに次のコードを追加し、<h:body>タグに現在含まれる内容を置き換えます。

           
              <h2>Hello, please log in:</h2>
              <h:form>
                  <h:panelGrid columns="2">
                      <h:outputLabel for="j_username"
                                     value="Please type your user name : "/>
                      <h:inputText id="j_username" value="#{loginBean.userName}"
                                   autocomplete="off" size="20"/>

                      <h:outputLabel for="j_password"
                                     value="Please type your password : " />
                      <h:inputSecret id="j_password" value="#{loginBean.password}"
                                     autocomplete="off" size="20"/>
                  </h:panelGrid>
                  <h:panelGroup>
                      <h:commandButton value="Submit" action="#{loginBean.login}"
                                       type="submit"/>
                      <h:commandButton value="Clear" type="reset"/>
                  </h:panelGroup>
              </h:form>
              <h:form styleClass="settings-form" rendered="#{request.userPrincipal ne null}">
                  You are logged in as #{request.userPrincipal.name}
                  <h:commandButton action="#{loginBean.logout}" value="Logout"/>
              </h:form>

      4.1. <title>の内容をLogin Pageに変更します。

      login.xhtmlは、ユーザー・データとパスワード・データを収集するためにJavaServer Facesで作成したログイン・フォームです。 ユーザーがSubmitボタンをクリックすると、loginBeanのloginメソッドがアクションとして呼び出されます。次の項では、loginBean.loginメソッドがServlet 3.0のHttpServletRequestインタフェースのloginメソッドを使用しており、Webアプリケーションに対するユーザー認証をプログラムで実行できることを確認します。

      login.xhtmlはユーザーがログイン済みである場合を考慮に入れており、この場合は"You are logged in as ..."という説明文をログイン・フォームの下に表示します。また、ボタンを押すとloginBean.logoutメソッドが呼び出され、現在のユーザーをログアウトできます。

    ログイン用マネージドBeanの作成

      プロジェクトを右クリックします。New」→「Other」を選択します。

      Categoriesから「Java Server Faces」を選択し、File Typesとして「JSF Managed Bean」を選択します。 「Next」をクリックします。

      Class NameにLoginBeanと入力します。

      Packageにcom.example.beansと入力します。

      Scopeに「request」を選択します。

      Finish」をクリックします。

      LoginBeanクラスにuserName変数とpassword変数を追加します。

            private String userName;
            private String password;

      LoginBean」のソースを右クリックします。

      Insert Code」をクリックします。

      Getter and Setter...」をクリックします。

      password」と「userName」を選択します。

      Generate」をクリックします。

      LoginBeanクラスに次のloginメソッドを追加します。

          public String login() {
              ExternalContext externalContext =
                      FacesContext.getCurrentInstance().getExternalContext();
              HttpServletRequest request = (HttpServletRequest) externalContext.getRequest();
              try {
                  request.login(userName, password);
                  return "index";
              } catch (ServletException ex) {
                  Logger.getLogger(LoginBean.class.getName()).log(Level.INFO,
                          "Failed to log in {0}", userName);
                  FacesContext facesContext = FacesContext.getCurrentInstance();
                  FacesMessage facesMessage = new FacesMessage(
                          "Failed to log in");
                  facesMessage.setSeverity(FacesMessage.SEVERITY_ERROR);
                  facesContext.addMessage(null, facesMessage);
                  return null;
              }
          }

      8.1. [Ctrl][Shift]を押しながら[I]を押し、Fix All Importウィンドウで「OK」をクリックして不足しているクラスをインポートします。

      loginメソッドはServlet 3.0のrequest.loginメソッドを使用し、渡されたユーザー名とパスワードを使用してログインします。

      LoginBeanクラスに次のlogoutメソッドを追加します。このメソッドは、HttpServletRequest.logoutメソッドを使用します。

          public String logout() {
              ExternalContext externalContext =
                      FacesContext.getCurrentInstance().getExternalContext();
              HttpServletRequest request = (HttpServletRequest) externalContext.getRequest();
              try {
                  request.logout();
                  return "login";
              } catch (ServletException ex) {
                  Logger.getLogger(LoginBean.class.getName()).log(Level.SEVERE,
                          "Failed to logout", ex);
              }
              return null;
          }

      logoutメソッドはServlet 3.0のrequest.logoutメソッドを使用して、現在のユーザーをログアウトします。

Indexファイルの更新とWebアプリケーションの起動

    ここでは、index.xhtmlページを更新し、現在のユーザーからログアウトできるようにします。 また、Webアプリケーションをデプロイし、Webブラウザでアプリケーションを起動します。

    Indexファイルの更新

      プロジェクトのWeb Pagesフォルダにあるindex.xhtmlファイルに、次のコードを追加します。

              <h:graphicImage url="Duke_Caesar.gif" alt="Duke as a caesar"/>
              <h2>Hello, you are logged in as #{request.userPrincipal.name}<br/></h2>
              <h:form styleClass="settings-form" rendered="#{request.userPrincipal ne null}">
                  <h:commandButton action="#{loginBean.logout}" value="Logout"/>
              </h:form>

      1.1. <title>の内容をSecure Duke Realmに変更します。

      Dukeのイメージをこちらからダウンロードし、NetBeansプロジェクトのWebフォルダにコピーします。

    Webアプリケーションのデプロイと起動

      プロジェクトを右クリックします。Deploy」をクリックします。

      WebLogic Serverが起動され、アプリケーションがデプロイされます。

      ブラウザを起動し、次のURLを入力します。 http://localhost:7001/SecureDukeRealm/

      ログイン・フォームのユーザー名としてwebuserと入力します。

      パスワードとしてwelcome2と入力します。

      Submit」をクリックします。

      webuserとしてWebアプリケーションに対して認可されているため、index.xhtmlの内容を表示できます。

      Logout」をクリックします。

      ログイン・フォームのユーザー名としてwebadminと入力します。

      パスワードとしてwelcome3と入力します。

      Submit」をクリックします。

      webadminとしてWebアプリケーションに対して認可されているため、index.xhtmlの内容を表示できます。

注釈を使用したサーブレットの保護とWebアプリケーションの起動

    ここでは、@ServletSecurity注釈を使用したサーブレットを作成し、サーブレットのURLへのアクセスをAdminロールに対してのみ認可します。

    注釈を使用したサーブレットの保護

      プロジェクトを右クリックします。 「New」→「Servlet...」を選択します。

      Class NameにAdminDukeRealmServletと入力します。

      Packageにcom.example.servletsと入力します。

      Finish」をクリックします。

      NetBeansによってAdminDukeRealmServlet.javaサーブレットが作成されます。

      AdminDukeRealmServletクラスに次の行を追加します。

      @ServletSecurity(@HttpConstraint(rolesAllowed = {"Admin"}))

      3.1. [Ctrl][Shift]を押しながら[I]を押し、不足しているクラスをインポートします。

      @ServletSecurity注釈を使用する場合、デプロイメント・ディスクリプタで設定を指定する必要はありません。

      AdminDukeRealmServletクラスのprocessRequestメソッドに次のコードを追加し、try句内の内容を置き換えます。

                  out.println("<html lang=\"en\">" + "<head><title>Hello</title></head>");
                  out.println(
                          "<body  bgcolor=\"#ffffff\">"
                          + "<img src=\"Duke_Caesar.gif\" alt=\"Duke as a caesar\">"
                          + "<form action=\"LogoutServlet\" method=\"get\">"
                          + "<h2>Hello, you are logged in as ");
                  out.println(request.getUserPrincipal().getName());
                  out.println(" and you are in a secured URL</h2>");
                  out.println("<p></p>" + "<input type=\"submit\" value=\"Logout\"/>");
                  out.println("</form></body></html>");
         

      ここではrequest.getUserPrincipal.getNameメソッドを使用して、プログラムでユーザーを特定しています。

      次のステップでは、現在のセッションを無効化することで、このサーブレットのログアウト・ボタンの処理を実行する新しいサーブレットを作成します。

      プロジェクトを右クリックします。 「New」→「Servlet...」を選択します。

      Class NameにLogoutServletと入力します。

      Packageにcom.example.servletsと入力します。

      Finish」をクリックします。

      NetBeansによってLogoutServlet.javaサーブレットが作成されます。

      LogoutServletクラスのprocessRequestメソッドに次のコードを追加し、try句内の内容を置き換えます。

                  HttpSession session = (HttpSession) request.getSession(false);
                  if (session != null) {
                      session.invalidate();
                  }
                  response.sendRedirect("login.xhtml");

      7.1. [Ctrl][Shift]を押しながら[I]を押し、不足しているクラスをインポートします。


      [Ctrl]を押しながら[S]を押し、アプリケーションを保存します。

    Webアプリケーションの起動と保護されたサーブレットへのアクセスのテスト

      Webアプリケーションにログインします。

      ブラウザを起動し、次のURLを入力します。 http://localhost:7001/SecureDukeRealm

      ログイン・フォームのユーザー名としてwebadminと入力します。

      パスワードとしてwelcome3と入力します。

      Submit」をクリックします。

      webadminとしてログインしました。

      webadminとしてサーブレットにアクセスします。

      Webブラウザに次のURLを入力します。 http://localhost:7001/SecureDukeRealm/AdminDukeRealmServlet

      webadminとして認可されているため、サーブレットの内容を表示できます。

      Logout」をクリックします。

      webuserとしてWebアプリケーションにログインします。

      ログイン・フォームのユーザー名としてwebuserと入力します。

      パスワードとしてwelcome2と入力します。

      Submit」をクリックします。

      Webブラウザに次のURLを入力します。 http://localhost:7001/SecureDukeRealm/AdminDukeRealmServlet

      Adminロールのみに許可されたサーブレットのURLにアクセスしようとしたため、エラー・メッセージが表示されています。

まとめ

    このチュートリアルで学習した内容は、次のとおりです。

    • WebLogic Serverへのユーザーの追加
    • セキュリティ制約の指定
    • ログイン・フォームの作成
    • ログイン・フォームの制御用マネージドBeanの作成
    • 注釈を使用したサーブレットへのアクセスの保護

    参考資料

    著者

    • カリキュラムの開発者: Edgar Martinez

このOracle by Exampleをナビゲートする際、次の機能を使用できます。

ヘッダー・ボタンの非表示:
ヘッダー内のボタンを非表示にするには、タイトルをクリックします。 ボタンを再表示するには、もう一度タイトルをクリックします。
トピック一覧ボタン:
すべてのトピックの一覧です。 いずれかのトピックをクリックすると、その項に移動します。
すべてのトピックを開く/閉じる:
すべての項に対する詳細を表示または非表示にします。 デフォルトでは、すべてのトピックが閉じられています。
すべてのイメージを表示/非表示:
すべてのスクリーンショットを表示または非表示にします。 デフォルトでは、すべてのイメージが表示されています。
印刷:
コンテンツを印刷します。 現在表示または非表示にされているコンテンツが印刷されます。

このチュートリアルの特定の項に移動するには、一覧からトピックを選択してください。