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をダウンロードし、インストールしていること。
シナリオ
このチュートリアルでは、以下を実行します。
前提条件
このチュートリアルを始める前に以下のことを確認してください。
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」をクリックします。

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>タグに、UserとAdminという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レルムに定義したwebadminとwebuserという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の作成
- 注釈を使用したサーブレットへのアクセスの保護
- The Java EE 6 Tutorial. Part VII: Security.
- Oracle Fusion Middleware Programming Security for Oracle WebLogic Server.
- Installing, Configuring and Testing WebLogic Server 12c Developer Zip Distribution in NetBeans OBE.
- JavaServer Faces Technology.
- カリキュラムの開発者: Edgar Martinez
このチュートリアルで学習した内容は、次のとおりです。
参考資料
著者
このOracle by Exampleをナビゲートする際、次の機能を使用できます。
- ヘッダー・ボタンの非表示:
- ヘッダー内のボタンを非表示にするには、タイトルをクリックします。 ボタンを再表示するには、もう一度タイトルをクリックします。
- トピック一覧ボタン:
- すべてのトピックの一覧です。 いずれかのトピックをクリックすると、その項に移動します。
- すべてのトピックを開く/閉じる:
- すべての項に対する詳細を表示または非表示にします。 デフォルトでは、すべてのトピックが閉じられています。
- すべてのイメージを表示/非表示:
- すべてのスクリーンショットを表示または非表示にします。 デフォルトでは、すべてのイメージが表示されています。
- 印刷:
- コンテンツを印刷します。 現在表示または非表示にされているコンテンツが印刷されます。
このチュートリアルの特定の項に移動するには、一覧からトピックを選択してください。