NetBeans IDEでのWebアプリケーションのセキュリティ保護

## 学習内容
JavaEEにおける認証について、以下のページを試します。

https://netbeans.apache.org//kb/docs/web/security-webapps_ja.html

---
## NetBeans IDEのセットアップ方法

NetBeans IDEをセットアップします。
NetBeans IDEを日本語でインストールする方法については、
以下のページが非常に詳しいです。

https://www.doraxdora.com/blog/2020/08/06/post-12450/

---
## Payaraサーバーのダウンロード

以下の Payaraサーバーの配布サイトから、多国語版をダウンロードします。
Multi-Language、Full とキーワードで探してダウンロードします。

https://www.payara.fish/downloads/payara-platform-community-edition/

---
## 展開
ダウンロードしたファイルは、Zip圧縮されているので、任意の場所に展開します。
ただし、Windows 環境の場合では C:\Program Files などスペース入りのフォルダは避けた方が無難です。
今回では、C:\apl というフォルダに展開しました。
![pic044.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/9f5e749d-09d7-830b-404b-ec9a1ca84d87.png)

---
## 管理パスワードの登録（１）
Payara の既定では、管理パスワードが設定されていません。リモートアクセスを有効にするのに先立って、まず管理パスワードを設定する必要があります。
管理パスワードの設定には asadmin change-admin-password コマンドを使用します。
![pic046.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/1187cfc5-14b6-bb64-de9e-ea59a5b8a4d6.png)

---
## 管理パスワードの登録（２）
ここでは、管理ユーザー名の決定と、管理パスワードの変更という 2 種類の操作を行います。入力項目は、以下の通りです。

1. 管理ユーザー名: 既定の admin を使用する場合は空欄とします
2. 現在の管理パスワード: 既定では管理パスワードは設定されていないため空欄とします
3. 新しい管理パスワード: 管理パスワードを入力します
4. 新しい管理パスワード: 入力した管理パスワードと同じものを確認のため入力します

Command change-admin-password executed successfully. と印字されたら成功です。
![pic047.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/cc550019-765e-8144-4339-a8a1a36dd927.png)

---
## セキュア管理の有効化（１）
リモートアクセスのためにセキュア管理 (HTTPS 通信) を有効化します。セキュア管理の有効化／無効化は Payara Server が起動している必要があるため、まず asadmin start-domain コマンドで Payara Server を起動します。
![pic049.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/134e4ea1-8a69-c8b8-25d1-b036991a9a81.png)

---
## セキュア管理の有効化（２）
続いて、asadmin enable-secure-admin コマンドでセキュア管理を有効化します。その際には、先に設定した管理ユーザー名 (admin) と管理パスワードを入力する必要があります。

```
C:\apl\payara5>.\bin\asadmin enable-secure-admin
Enter admin user name> admin
Enter admin password for user "admin">
セキュリティ保護された管理に対する変更を有効にするには、稼働中のすべてのサーバーを再起動する必要があります。
Command enable-secure-admin executed successfully.

```
## セキュア管理の有効化（３）
セキュア管理を有効化した後は、Payara Server を再起動する必要があります。
再起動を行う asadmin restart-domain コマンドを使用した方が高速です。

```
C:\apl\payara5>.\bin\asadmin restart-domain
Successfully restarted the domain
Command restart-domain executed successfully.
```
---
## セキュア管理の有効化（４）
リモートアクセスを有効にする際に、enable-secure-admin を設定していますが、これにより管理コンソールへのアクセスが HTTP から HTTPS (HTTP over SSL/TLS) に変更され、暗号化通信となります。
GlassFish 3.1.2 あたりから管理コンソールへのリモートアクセスは HTTPS に限定されるようになっています。
Payara Server のインストール直後は電子証明書のチェーンが整備されていないため、ブラウザ側で一旦アクセスをブロックされますが、イントラネット上であるため無視してアクセスを強行してください。その後、Payara の管理コンソールにアクセスできるようになります。

![pic050.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/8a240c5b-15d8-d79c-9aa1-1d5a001ed99e.png)

![pic051.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/59c13faf-66e0-ac16-0947-12c91ed5cfb2.png)

![pic052.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/612b07e4-9289-df2d-3a6e-ff07975e2193.png)

---
## サーバーのインストール
サーバー・インスタンスがIDEに登録されていることを確認します。IDEが起動したら、メニューバーから[ツール]-[サーバー]を選択します。
![pic017.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/fb0becf4-643c-7f1b-cea3-1857441061de.png)

---
## サーバーの追加
サーバー設定の画面が開けたら、サーバーの追加のボタンをクリックします。
![pic018.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/b901d7fe-ceb6-bd88-f068-cc3a0856e825.png)

---
## Payaraサーバーの追加
サーバーの種類として、Payara Serverを選択し、次へ ボタンをクリックします。
![pic034.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/78c71743-3c98-9a43-0805-dcd2a5998b19.png)

---
## サーバーの指定
Installation Location に、先ほどの Payaraサーバーの展開場所を指定します。
今回の例だと、C:\apl\payara5 となっています。
![pic045.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/e6a620fe-8c41-1117-74d6-0d41d8bb0b65.png)

---
## ドメインの指定
次の画面では、デフォルトのままで、終了ボタンをクリックします。
![pic036.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/dfb2e95a-6ac4-c75d-7aff-5df98675e90c.png)

---
## サーバーの追加の完了

このようにサーバーの追加が完了しました。
![pic037.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/5e21d6f9-c4bd-40f4-f50b-afdec60f1ce5.png)

---
## 注意事項
自分の場合、サーバーのJDKのバージョンが11の場合、動作できませんでした。
JDKのプラットフォームを以下のようにJDK1.8に設定してください。
![pic038.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/0df1d7e6-abe2-dc3e-c2b3-4e26a735bd06.png)

---
## Webアプリケーションの作成
この課題では、まずWebアプリケーション・プロジェクトとディレクトリ構造を作成します。
次に、セキュリティ保護された各ディレクトリで、単純な html ファイルをいくつか作成します。
Webアプリケーションは、セキュリティ保護されたディレクトリへのアクセスに、
ひとまず、BASIC認証を使用します。

---
## Webアプリケーションプロジェクトの作成
「ファイル」>「新規プロジェクト」([Ctrl]-[Shift]-[N])を選択し、
カテゴリ (Maven) - プロジェクト(Webアプリケーション)を選択して、次へボタンをクリックします。
![pic023.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/8d13e320-fd3c-a671-7714-9323772ddd13.png)

---
## プロジェクト名の指定
自分は、Mavenのほうが使いやすいのでこのようにしていますが、Gradleの方がよい方は、Gradleを使ってコンテンツの内容については適宜読み替えてください。
プロジェクト名に「WebApplicationSecurity」を指定し、デフォルトの設定を受け入れます。
![pic024.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/5267dfdd-b330-bfd2-b805-d97592d38fb8.png)

---
## デプロイするサーバーの選択
アプリケーションをデプロイするサーバーを選択します。表示されるのは、IDEに登録されているサーバーのみです。
![pic039.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/6b5cce6e-ac83-28cb-2a04-b7eb38a04059.png)

---
## ディスクリプタの生成（１）
Payara_Server とNetBeans IDE 7.0.1以降を使用している場合は、サーバー固有のディスクリプタを生成する必要があります。プロジェクトのノードを右クリックし、「新規」>「その他」>「Payara」>「Payara Descriptor」を選択し、次へボタンをクリックします。
![pic040.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/19ebd933-d7be-82d1-ea19-774a6e768d3b.png)

---
## ディスクリプタの生成（２）
「New Payara Descriptor」ダイアログが開きます。デフォルトをすべて受け入れ、「終了」ボタンをクリックします。
![pic041.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/6095b15e-2fa8-c43e-7344-b074e5f6e3f7.png)

---

## セキュリティ保護されたフォルダの作成（１）
IDEの「プロジェクト」ウィンドウで「Webページ」を右クリックし、「新規」>「フォルダ」を選択します。
新規フォルダ・ウィザードでフォルダに「secureAdmin」という名前を付け、「終了」をクリックします。
![pic028.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/f8e258f9-b479-af7e-4aa0-dbaf89bf0261.png)

---
## セキュリティ保護されたフォルダの作成（２）
前の3つの手順を繰り返して、「secureUser」という名前の別のフォルダを作成します。
![pic029.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/335735ed-d158-b640-508e-38b781b422fc.png)

---
## セキュリティ保護されたページの作成（１）
プロジェクト」ウィンドウで、secureUserフォルダを右クリックして「新規」>「HTML」を選択し、secureUserフォルダ内に新しい html ファイルを作成します。
新しいファイルにpageUという名前を付け、「終了」をクリックします。
![pic030.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/0a1e8f5f-1087-6e30-ffbf-7e06764104b0.png)

---
## セキュリティ保護されたページの作成（２）
「終了」をクリックすると、ソース・エディタでファイル pageU.html が開きます。
デフォルトで作成されたHTMLテンプレートファイルを以下のように置き換えます。

```html:secureUser/pageU.html
<!DOCTYPE html>
<html>
    <head>
        <title>User secure area</title>
        <meta charset="UTF-8">
    </head>
    <body>
        <h1>User Secure Area</h1>
    </body>
</html>
```
---
## セキュリティ保護されたページの作成（３）

secureAdminフォルダを右クリックし、pageAという名前の新しい html ファイルを作成します。
デフォルトで作成されたHTMLテンプレートファイルを以下のように置き換えます。

```html:secureAdmin/pageA.html
<!DOCTYPE html>
<html>
    <head>
        <title>Admin secure area</title>
        <meta charset="UTF-8">
    </head>
    <body>
        <h1>Admin secure area</h1>
    </body>
</html>
```

---
## JSPのインデックス・ページの作成
セキュリティ保護された領域へのリンクを含むJSPのインデックス・ページを作成します。ユーザーがリンクをクリックすると、ユーザー名とパスワードの入力が求められます。
BASIC認証を使用している場合は、デフォルト・ブラウザのログイン・ウィンドウが表示されます。ログイン・フォーム・ページを使用する場合、ユーザーはフォームにユーザー名とパスワードを入力します。
![pic031.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/eb6932f6-83a7-eb4f-6fa9-58b248fb4010.png)

```html:index.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>
    </head>
    <body>
        <p>Request a secure Admin page <a href="secureAdmin/pageA.html" >here!</a></p>
        <p>Request a secure User page <a href="secureUser/pageU.html" >here!</a></p>
    </body>
</html>
```
---
## ターゲット・サーバーでのユーザーの作成
Webアプリケーションにて、BASIC認証 あるいは FORM認証等、ユーザーおよびパスワードによる認証を使用できるようにするには、ユーザーとその適切なロールがターゲット・サーバーに定義されている必要があります。サーバーにログインするには、そのサーバーにユーザー・アカウントが存在している必要があります。

ユーザーとロールの定義方法は、ターゲット・サーバーに応じて異なります。
このチュートリアルでは、セキュリティの設定をテストするために、 admin ユーザーと user ユーザーを使用します。これらのユーザーがそれぞれのサーバーに存在し、適切なロールがユーザーに割り当てられていることを確認する必要があります。

---
## Payara サーバーでのユーザーの定義
このシナリオでは、Payaraサーバーの管理コンソールを使用して、 user と admin という名前の2つの新しいユーザーを作成する必要があります。 user という名前のユーザーにはアプリケーションへのアクセス権を制限し、 admin には管理権限を付与します。

---
## 管理コンソール
IDEの「サービス」ウィンドウに移動して「サーバー」>「Payara Server」を右クリックし、「View Domain Admin Console」を選択して管理コンソールを開きます。
![pic042.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/6ca079b3-5ebc-a4ca-10fd-c600c2190ca4.png)

---
## 管理コンソールのログイン画面
管理コンソールにアクセスするには、adminのユーザー名とパスワードを使用してログインする必要があります。管理者のユーザー名とパスワードについては前述したを設定内容でログインします。
![pic052.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/b9678c54-4c57-0819-1753-2a334ca157f4.png)

---
## Payaraサーバーでのユーザーの定義（１）
管理コンソールで、「構成」>「server-config」>「セキュリティ」>「レルム」>「file」の順に展開します。「レルムを編集」パネルが開きます。
![pic053.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/7b5aea1f-1613-1a88-6728-337ca18340ed.png)

---
## Payaraサーバーでのユーザーの定義（２）
「レルムを編集」パネルの上部にある「ユーザーの管理」ボタンをクリックします。「ファイル・ユーザー」パネルが開きます。
![pic054.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/df3316ad-74bb-f4c7-5409-d8df96273183.png)
![pic055.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/6fdb6420-0269-205f-d280-f713db125246.png)

---
## Payaraサーバーでのユーザーの定義（３）
「新規」をクリックします。新規ファイル・レルム・ユーザー・パネルが開きます。「ユーザーID」に「 user 」、パスワードに「 user 」と入力します。「OK」をクリックします。
![pic056.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/1c3932d8-80e4-a3e7-3aa3-b2e625583346.png)

---
## Payaraサーバーでのユーザーの定義（４）
user が作成されました。
![pic057.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/f47eedb4-b729-f350-c617-11da106eda1a.png)

前の手順に従って、名前が「admin」、パスワードが「admin」のユーザーを file レルムに作成します。

![pic058.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/da11cf2d-eef0-1113-cf77-00b393bc2ff5.png)

---
## ログイン方法の構成（１）
ここからはしばらく座学的な話になります。

アプリケーションのログイン方法を構成するには、ブラウザによって提供されるBASIC認証のログイン・ウィンドウを使用できます。

または、ログイン・フォームがあるWebページを作成できます。
両方のタイプのログイン構成は、ユーザー名およびパスワードによる認証に基づいています。

---
## ログイン方法の構成（２）
ログインを構成するには、web.xml に、_セキュリティ制約_を作成し、ロールをこれらのセキュリティ制約に割り当てます。

_セキュリティ制約_ とは、web.xml における security-constraint 要素 のことを指します。

security-constraint 要素 は、何ぞやということは、以下のページが詳しいです。

https://access.redhat.com/documentation/ja-jp/jboss_enterprise_application_platform/5/html/security_guide/j2ee_declarative_security_overview-web_content_security_constraints

セキュリティ制約では一連のファイルを定義します。ロールを制約に割り当てると、そのロールを持つユーザーは、制約によって定義された一連のファイルにアクセスできるようになります。

---
## ログイン方法の構成（３）
たとえば、このチュートリアルでは、UserRoleをUserConstraintに
AdminRoleをAdminConstraintとUserConstraintに割り当てます。
これは、AdminRoleを持つユーザーはAdminファイルとUserファイルの両方にアクセスでき、UserRoleを持つユーザーはUserファイルのみにアクセスできることを意味します。

Constraint は、日本語訳すると 制約という意味です。

---
## BASIC認証

BASIC認証 を使用する場合は、ログイン・ウィンドウがブラウザに表示されます。セキュリティ保護されたコンテンツにアクセスするには、有効なユーザー名とパスワードが必要です。

以降、PayaraサーバーでのBASIC認証の構成方法を示します。

---
## BASIC認証の構成方法（１）
「プロジェクト」ウィンドウでWebページ- WEB-INF - web.xml を探して開きます。
![pic059.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/50a40eae-d384-4ab6-390a-9e0df4dea402.png)

参考にしたサイトでは、web.xml がビジュアルエディタで開きますと書かれていましたが、普通のXMLエディタで開かれましたので、読み替えが必要になりました。

## BASIC認証の構成方法（２）
「ログイン構成」というのは、web.xml における <login-config>要素のことです。以下を追加します。レリム名に、「file」と入力します。これは、Payaraサーバーで作成した場所のデフォルト・リレム名です。
<login-config>要素は、web.xml で１つしか存在しえないそうです。

``` WEB-INF/web.xml
<login-config>
  <auth-method>BASIC</auth-method>
  <realm-name>file</realm-name>
</login-config>

```
## BASIC認証の構成方法（３）
続いて、セキュリティ・ロールを追加します。
次のセキュリティロールを追加します。

|ロール名|意味|
|:--|:--|
|AdminRole|このロールに追加したユーザーは、サーバーのsecureAdmin ディレクトリへのアクセス権を持ちます。|
|UserRole|このロールに追加したユーザーは、サーバーの secureUser ディレクトリへのアクセス権を持ちます。|

**注意**
Payaraサーバーでのロール名は、先頭が大文字である必要があります。

タグは、次のようになります。

```WEB-INF/web.xml
<security-role>
  <role-name>AdminRole</role-name>
</security-role>

<security-role>
  <role-name>UserRole</role-name>
</security-role>
```
---
## BASIC認証の構成方法（４）
続いてセキュリティ制約を追加します。
セキュリティ制約は、\<security-constraint>要素で表されます。

\<security-constraint>要素には、以下の要素を含むことができます。

|要素タグ|意味|設定数|
|:--|:--|:--|
|\<web-resource-collection>|アクセス制限するWebリソースの設定|１つ以上(必須)|
|\<auth-constraint>|アクセスできるロールの設定|１つ以上(必須)|
|\<display-name>|表示名|省略可|
|\<user-data-constraint>|サーバー接続のクライアントのトランスポートレイヤに対する要件を指定|省略可|

---
## BASIC認証の構成方法（５）

\<web-resource-collection>要素は、以下の要素を含むことができます。

|要素タグ|意味|設定数|
|:--|:--|:--|
|\<web-resource-name>|識別する名前|必須|
|\<url-pattern>|ウェブリソースと一致するURLの定義|１つ以上(必須)|
|\<http-method>|適用されるHTTPメソッド<br>未指定の場合、全HTTPメソッドに対して適用される。|省略可|
|\<description>|説明|省略可|

\<auth-constraint>要素は、以下の要素を含むことができます。

|要素タグ|意味|設定数|
|:--|:--|:--|
|\<role-name>|識別する名前|必須|
|\<description>|説明|省略可|

---
## BASIC認証の構成方法（６）
AdminConstraint という名の制約は、次のようになります。

```
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Admin</web-resource-name>
            <url-pattern>/secureAdmin/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>AdminRole</role-name>
        </auth-constraint>    
    </security-constraint>
```
---
## BASIC認証の構成方法（７）
UserConstraint という名の制約は、次のようになります。

```
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>User</web-resource-name>
            <url-pattern>/secureUser/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>AdminRole</role-name>
            <role-name>UserRole</role-name>
        </auth-constraint>
    </security-constraint>
```

セッションの持続時間を指定します。デフォルトは30分です。

```
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
```

最初に探すファイル(welcomeファイル)を指定します。

```
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
```
---
## BASIC認証の構成方法（８）

最終的なweb.xml は、次のようになりました。

``` WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
   version="4.0">
    
    <login-config>
        <auth-method>BASIC</auth-method>
        <realm-name>file</realm-name>
    </login-config>

    <security-role>
      <role-name>AdminRole</role-name>
    </security-role>

    <security-role>
      <role-name>UserRole</role-name>
    </security-role>

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Admin</web-resource-name>
            <url-pattern>/secureAdmin/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>AdminRole</role-name>
        </auth-constraint>    
    </security-constraint>
    
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>User</web-resource-name>
            <url-pattern>/secureUser/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>AdminRole</role-name>
            <role-name>UserRole</role-name>
        </auth-constraint>
    </security-constraint>
    
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
          
</web-app>
```
---
## ユーザーとロールを紐づける
Payaraサーバーの場合、ユーザーとロールを紐づけるためのファイルとして、payara-web.xml を編集する必要があります。
\<principal-name>（プリンシパル名)という謎のタグが出てきましたが、調べたところユーザー名を指定すれば良いようです。

``` WEB-INF/payara-web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE payara-web-app PUBLIC "-//Payara.fish//DTD Payara Server 4 Servlet 3.0//EN" "https://docs.payara.fish/schemas/payara-web-app_4.dtd">
<payara-web-app error-url="">
  <security-role-mapping>
    <role-name>AdminRole</role-name>
    <principal-name>admin</principal-name>
  </security-role-mapping>
  <security-role-mapping>
    <role-name>UserRole</role-name>
    <principal-name>user</principal-name>
  </security-role-mapping>
  <class-loader delegate="true"/>
</payara-web-app>
```
---
## 動作確認（１）
自分の場合、かなり苦戦したのですがとりあえずうまくいきました。

以下のURLにアクセスすると、作成したindex.jsp にアクセスできるはずです。

![pic060.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/486a7ff0-d059-0fc3-c741-4ec63b1ac584.png)

Request a secure Admin page here! の方をクリックすると、次のようなダイアログ画面が出ます。
![pic061.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/58d6bf67-f3a2-9a1c-81fc-d2b8139b4865.png)

ここでユーザー名：adminとadminのパスワードを入力すると、adminユーザー用のページが開かれます。
![pic062.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/985f05c4-5bb1-db6b-387c-6944be2d2284.png)

戻るボタンを押して、Request a secure User page here!の方をクリックすると、adminユーザーなので ユーザー専用ページにもアクセスできます。
![pic063.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/4fddee8f-9528-3ad4-f740-2230a25f8f18.png)

この場合、ブラウザにユーザー名とパスワードが記録されている状態です。ブラウザをすべて閉じることで、記録がクリアされ、最初からやり直しになります。

---
## 動作確認（２）
すべてのブラウザを閉じて、Request a secure Admin page here!  のリンクを今度はuserでログインします。

userでログインすると、アクセス権が無い旨の画面が表示されます。

![pic064.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/dc6f3403-bf28-e60f-b0fe-0733d3fc82c8.png)

戻って、Request a secure User page here! のリンクを踏むと、ユーザーエリアの画面が表示されます。
![pic063.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/4fddee8f-9528-3ad4-f740-2230a25f8f18.png)

---
## まとめ
Payara (JavaEEサーバー)におけるアクセス制限についての学習ができました。
結果的に、NetBeansのセットアップ方法、Payaraサーバーのインストール方法や設定方法、mavenプロジェクトの作成、NetBeans IDEの簡単な使い方、アプリケーションの実行方法も学ぶことができました。

~~FORM認証、DIGEST認証についてもこのページで追加出来たら良いかもしれません。~~

---
## FORM認証
BASIC認証の代わりにログインフォームを作成する場合、フォームを含むJSPページを作成できます。
ログイン方法の構成で、ログインページとエラーページを指定します。

プロジェクトのウィンドウで、「Webページ」フォルダを右クリックし、
「新規」＞「JSP」を選択します。
ファイルにloginという名前を付けて、その他のフィールドはデフォルトのままにし、「終了」ボタンをクリックします。
![pic065.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/25695f41-1405-d561-7f6f-d4bdf64ca4ee.png)

---
## ログインフォームの作成
作成されたJSPファイルを以下のように置き換えます。

``` HTML:login.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Login Page</title>
    </head>
    <body>
        <form method="POST" action='<%= response.encodeURL("j_security_check") %>'>
            <table cellspacing="5">
                <tr>
                    <th align="right">Username:</th>
                    <td align="left"><input type="text" name="j_username"></td>
                </tr>

                <tr>
                    <th align="right">Password:</th>
                    <td align="left"><input type="password" name="j_password"></td>
                </tr>

                <tr>
                    <td align="right"><input type="submit"></td>
                    <td align="left"><input type="reset"></td>
                </tr>
            </table>
        </form> 
    </body>
</html>
```

---
## エラーページの作成
loginError.html という名の新しいhtmlファイルを「Webページ」フォルダに作成します。
ソースエディタで、loginError.html を次のコードに置き換えます。

``` HTML:loginError.html
<!DOCTYPE html>
<html>
    <head>
        <title>Login Error</title>
        <meta charset="UTF-8">
    </head>
    <body>
        <h1>Error Logging In</h1>
        <br>
    </body>
</html>
```
---
## ログイン構成の変更
ログイン用のフォームを使用するために、ログイン構成を変更します。
Webページ/WEB-INF/web.xml を開きます。

ログイン構成の設定値である\<login-config> 要素を以下のように変更します。

``` HTML:WEB-INF/web.xml

    <login-config>
        <auth-method>FORM</auth-method>
        <form-login-config>
            <form-login-page>/login.jsp</form-login-page>
            <form-error-page>/loginError.html</form-error-page>
        </form-login-config>
    </login-config>
```

---
## 動作確認
Request a secure Admin page here! をクリックすると、以下のようなフォームが表示されるようになりました。
![pic066.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/6fee65c3-2df0-880a-9193-944a702fabec.png)

不正なユーザー名、またはパスワードを入力すると、エラーページが表示されます。
![pic067.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/548a9402-e827-0671-903a-43a08e973720.png)

正しいユーザー名、パスワードを入力した場合は、これまで通りです。

---
## エラーページの修正
アクセス権限が無い場合、次のようなエラーページが出力されるのは、よろしくはありません。
理由としては、サーバーのバージョン情報が表示されており、バージョン情報から脆弱性に対するヒントを与えてしまうからです。

![pic064.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/4ec946eb-06e6-a1c9-154a-db8098798460.png)

以下のようなエラーページを作成します。

```html:WEB-INF/error/403.html
<!DOCTYPE html>
<html>
    <head>
        <title>認証エラー</title>
        <meta charset="UTF-8">
    </head>
    <body>
        <p>認証エラー</p>
    </body>
</html>
```

WEB-INF/web.xml に以下の定義を追加します。

```html:WEB-INF/web.xml
    <error-page>
        <error-code>403</error-code>
        <location>/WEB-INF/error/403.html</location>
    </error-page>
```
---
## 動作確認
かなりしょぼいですが、カスタマイズされたエラーページが表示されるようになりました。

![pic068.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/620872bb-2593-a8a0-4493-840384870e35.png)

---

## JDBCリレム
ここまでのやり方では、ユーザーやパスワードなどの情報はファイルに格納されていました。JDBCレリムを使用してデータベースに情報を格納するようにします。

JDBCレリムを使用するには、２段階の準備が必要です。
まずは、データベースにユーザー認証用のデータを作成します。

Payaraサーバーには、H2データベースが同梱されているので、H2データベースを使って試します。
H2データベースを起動するためのバッチファイルは、
\<Parayaサーバーのインストールフォルダ>\h2db\bin\h2.bat です。

ただ、このままでは起動できないため、コピーをしてサーバーモードで起動する新しいバッチファイルを作成します。

```dosbatch:payara5\h2db\bin\h2.bat(変更前)
@java -cp "h2-1.4.196.jar;%H2DRIVERS%;%CLASSPATH%" org.h2.tools.Console %*
@if errorlevel 1 pause
```

```dosbatch:payara5\h2db\bin\h2_server.bat(変更後)
@java -cp "h2.jar;%H2DRIVERS%;%CLASSPATH%" org.h2.tools.Server %*
@if errorlevel 1 pause
```

実行すると、接続するためのウィンドウが開かれます。
保存済設定： Generic H2(Server)を選択し、デフォルトのままで接続テストを
実施すると、以下のようになると思います。

![pic069.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/2a7dd40d-c0ef-603c-a815-e0adc89658f4.png)

接続すると、testデータベースに接続できます。
以下のSQLを流してテーブルと初期データを作成します。

```SQL:CreateAndInsert.sql
-- テーブルドロップ
DROP TABLE IF EXISTS USERTABLE;
DROP TABLE IF EXISTS GROUPTABLE;
-- パスワード変更
-- H2データベースのsa アカウントのパスワードはデフォルトではパスワードなしだが
-- Payaraサーバーの接続プールの設定でパスワードなしの設定は拒否されるので、パスワードを変更する。
ALTER USER sa SET PASSWORD 'sa';
-- ユーザーテーブル
CREATE TABLE USERTABLE(
   USERID VARCHAR(30) PRIMARY KEY,
   PASSWORD CHAR(64) NOT NULL
);
-- グループテーブル
CREATE TABLE GROUPTABLE(
   USERID VARCHAR(30) PRIMARY KEY REFERENCES USERTABLE (USERID),
   GROUPID VARCHAR(256) NOT NULL
);

-- ユーザー・テーブルの初期データ
-- サンプルのためパスワードはユーザー名と同じ値に設定している
INSERT INTO USERTABLE VALUES('tanaka', HASH('SHA256', STRINGTOUTF8('tanaka'), 1));
INSERT INTO USERTABLE VALUES('yamada', HASH('SHA256', STRINGTOUTF8('yamada'), 1));
INSERT INTO USERTABLE VALUES('sasaki', HASH('SHA256', STRINGTOUTF8('sasaki'), 1));
COMMIT;

-- グループ・テーブルの初期データ
INSERT INTO GROUPTABLE VALUES('tanaka', 'admin');
INSERT INTO GROUPTABLE VALUES('yamada', 'user');
INSERT INTO GROUPTABLE VALUES('sasaki', 'user');
COMMIT;
```
パスワードの内容は、ユーザー名と同じ内容をSHA-256でハッシュ化した内容を設定しています。

なお、H2データベースの管理者ユーザーとして存在している sa というユーザーですが、
デフォルトではパスワードなしとなっています。
ただ、parayaサーバーのJDBC接続プールの設定で、パスワードなしの場合、エラーとなってしまうので、パスワードを設定する必要があります。

---
## Parayaサーバー側の設定（１）
まずはじめにJDBC接続プールを作成します。
JDBC接続プールを作成するには、管理コンソールからのウィザードを使用するのが便利です。

リソース-JDBC接続プールを選択すると新規JDBC接続プール(ステップ1/2)のウィザードが始まります。

![pic047.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/05b19a41-89d5-d841-fa5c-ef13a8e3ff2e.png)

|項目|設定価|
|:--|:--|
|プール名|任意のプール名(今回は、SampleH2Pool)|
|リソースタイプ|javax.sql.DataSource|
|データベース・ドライバのベンダー|H2|
|イントロスペクト|無効(チェックなし)|
|データソース・クラス名|org.h2.jdbcx.JdbcDataSource|
|追加プロパティ||
|User|sa|
|Url|jdbc:h2:tcp://localhost/~/test|
|LoginTimeout|0|
|Password|sa|

コマンドラインから、JDBC接続プールの一覧を表示するには、list-jdbc-connection-pools サブコマンドを投入します。

```
C:\Apl\payara5>.\bin\asadmin list-jdbc-connection-pools
Enter admin user name> admin
Enter admin password for user "admin">
__TimerPool
H2Pool
SamplePool
SampleH2Pool
Command list-jdbc-connection-pools executed successfully.
```

また、接続プールが使用可能かどうか確認するために、pingを打ってみます。

```
C:\apl\payara5>.\bin\asadmin ping-connection-pool SampleH2Pool
Enter admin user name> admin
Enter admin password for user "admin">
Command ping-connection-pool executed successfully.
```

---
## Parayaサーバー側の設定（２）
続いてJDBCリソースを作成します。
create-jdbc-resource サブコマンドを投入し作成します。

```
C:\Apl\payara5>.\bin\asadmin create-jdbc-resource --connectionpoolid SampleH2Pool jdbc/security
Enter admin user name> admin
Enter admin password for user "admin">
JDBCリソースjdbc/securityは正常に作成されました。
Command create-jdbc-resource executed successfully.
```
---
## Parayaサーバー側の設定（３）
管理コンソールにログインし、「構成」-「server-config」-「セキュリティ」- 「レルム」とメニューをたどりレルムの構成画面を表示します。
![pic070.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292074/7f93e28a-5c70-bd9c-8c74-e153cdfaf0fd.png)

デフォルトではJDBCレルムは作成されていませんので、[新規...] ボタンをクリックしてレルムを作成します。設定項目は以下の通りです。

|プロパティ|設定値|
|:--|:--|
|レルム名|任意 (例えば jdbc など)|
|クラス名|com.sun.enterprise.security.auth.realm.jdbc.JDBCRealm|
|JAASコンテキスト|jdbcRealm|
|JNDI|jdbc/security|
|ユーザー表|USERTABLE|
|ユーザー名列|USERID|
|パスワード列|PASSWORD|
|グループ表|GROUPTABLE|
|グループ表ユーザー名列|USERID|
|グループ名列|GROUPID|
|グループ割当て|(空欄)|
|データベース・ユーザー|(空欄)|
|データベース・パスワード|(空欄)|
|ダイジェスト・アルゴリズム|SHA-256|
|エンコーディング|Hex|
|文字セット|(空欄)|

---
## 認証方式の変更
Webページ/WEB-INF/web.xmlの\<login-config>要素を次のように変更します。

```html:WEB-INF/web.xml
    <login-config>
        <auth-method>FORM</auth-method>
        <realm-name>jdbc</realm-name>
        <form-login-config>
            <form-login-page>/login.jsp</form-login-page>
            <form-error-page>/loginError.html</form-error-page>
        </form-login-config>
    </login-config>
```

Webページ/WEB-INF/payara-web.xmlを次のように変更します。

```html:WEB-INF/payara-web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE payara-web-app PUBLIC "-//Payara.fish//DTD Payara Server 4 Servlet 3.0//EN" "https://docs.payara.fish/schemas/payara-web-app_4.dtd">
<payara-web-app error-url="">
  <security-role-mapping>
    <role-name>AdminRole</role-name>
    <group-name>admin</group-name>
  </security-role-mapping>
  <security-role-mapping>
    <role-name>UserRole</role-name>
    <group-name>user</group-name>
  </security-role-mapping>
  <class-loader delegate="true"/>
</payara-web-app>
```
---
## はまった内容
JDBCレクリムの設定ではまった内容についてメモしておきます。

JDBC接続プールを作り直した際（削除＆作成）、紐づいているJDBCリソースも
あわせて削除されることに気づかず、はまりました。
この場合のエラーが、JDBCリソースの指定が無いという直接的なエラーではなく、
ログインに失敗しました。というエラーメッセージが出ました。

具体的には、
  WEB9102: Web Login Failed: com.sun.enterprise.security.auth.login.common.LoginException: Login failed: userのJDBCログインに失敗しました。|#]

というメッセージでした。
JDBCリソースを無効にした状態でも同じでした。
直接的なメッセージではなく、かつ一度設定済みの内容が削除されるとは思っておらず、
思い込みが発生し、はまりました。

デフォルトで準備されているJDBC接続プールである「H2Pool」を流用しようと思ったのですが、
URLが、「jdbc:h2:${com.sun.aas.instanceRoot}/lib/databases/embedded_default;AUTO_SERVER=TRUE」となっており、
ネットワーク接続のそれと違い、流用できませんでした。

H2データベースのsa ユーザーがデフォルトでは、パスワードなしなのは知っていましたが、PayaraサーバーでパスワードなしでJDBCコネクションプールが作れないことを知らずにはまりました。
その場合、このようなエラーメッセージが出ました。

RAR5114 : Error allocating connection : [No password credential found]|#]

---
## まとめ
JDBCレリムを使った認証を設定したのですが、JDBC接続プールやJDBCリソースの内容についても、学べたので勉強になりました。

また、インターネットで調べた限りでは、H2のJDBC接続プールの作成方法については、
記載がないとの、JDBCリソースの作り方についても解説があまりなかったので、
記録に残せて幸いです。