17 PL/SQL Webアプリケーションの開発

注意:

この章で説明するテクノロジの使用は、HTTP通信およびHTML生成を厳密に制御する必要があるアプリケーションに適しています。他のアプリケーションの場合、アプリケーション開発を容易にするためにより多くの機能や便利なグラフィカル・インタフェースを備えたOracle Application Expressを使用することをお薦めします。

この章では、データベースをイントラネットで利用可能にする、PL/SQL Webアプリケーションの開発方法について説明します。

トピック:

関連項目:

Oracle Application Expressの使用の詳細は、『Oracle Application Expressアプリケーション・ビルダー・ユーザーズ・ガイド』を参照してください

PL/SQL Webアプリケーションの概要

一般的に、PL/SQLで作成されるWebアプリケーションは、HTTPを介してWebブラウザと対話するストアド・サブプログラムの集合です。相互リンクされた一連の動的に作成されたHTMLページが、Webアプリケーションのユーザー・インタフェースになります。

PL/SQL Webアプリケーションのプログラム・フローは、CGI PERLスクリプトのプログラム・フローに似ています。通常、開発者はCGIスクリプトを使用してWebページを動的に作成しますが、多くの場合それらのスクリプトはデータベースへのアクセスに適していません。PL/SQLストアド・サブプログラムでWebコンテンツを配信することによって、強力で柔軟なデータベース処理が実現されます。たとえば、データ操作言語(DML)、動的SQL文およびカーソルを使用できます。各HTTPリクエストを処理する新しいCGIプロセスをforkするためのプロセス・オーバーヘッドを解消することもできます。

図17-1に、PL/SQL Webアプリケーションの一般的なプロセスを示します。

図17-1 PL/SQL Webアプリケーション

図17-1の説明が続きます
「図17-1 PL/SQL Webアプリケーション」の説明

PL/SQL Webアプリケーションの実装

PL/SQL GatewayまたはPL/SQL Web Toolkitを使用して、完全にWebブラウザ・ベースのアプリケーションをPL/SQLに実装できます。

トピック:

PL/SQLゲートウェイ

PL/SQLゲートウェイは、WebブラウザがHTTPリスナーを介してPL/SQLストアド・サブプログラムを起動するのを可能にします。ゲートウェイとは、PL/SQLユーザーがPL/SQL Webアプリケーションを開発およびデプロイするプラットフォームのことです。

mod_plsql

mod_plsqlは、PL/SQLゲートウェイの実装の一例です。モジュールとはOracle HTTP Serverのプラグインのことで、WebブラウザがPL/SQLストアド・サブプログラムを起動するのを可能にします。Oracle HTTP Serverは、Oracle Application ServerおよびOracle Databaseのコンポートネントです。

mod_plsqlプラグインを使用すると、PL/SQLストアド・サブプログラムを使用して、HTTPリクエストを処理し、レスポンスを作成できます。このコンテキストでは、HTTPリクエストはストアド・サブプログラムに渡されるパラメータ値を含むURLです。PL/SQLゲートウェイではURLを変換し、そのパラメータでストアド・サブプログラムを起動し、クライアントに出力(通常はHTML)を戻します。

PL/SQLゲートウェイの埋込み形式と比較して、mod_plsqlを使用することのメリットには、次のものがあります。

  • ファイアウォール環境で実行できます。この環境では、Oracle HTTP Serverがファイアウォールに対応するホスト上で実行され、データベースはファイアウォールの内側にホストされます。埋込みゲートウェイではこの構成を使用できません。

  • 埋込みゲートウェイは、動的HTMLキャッシュ、システム監視、共通ログ形式でのロギングなどのmod_plsql機能をサポートしていません。

埋込みPL/SQLゲートウェイ

データベースのXML DB HTTP Listenerで稼働するPL/SQLゲートウェイの埋込みバージョンを使用できます。これにより、mod_plsqlのコア機能がデータベースに提供されますが、Oracle HTTP Serverは必要ありません。PL/SQL Web ToolkitにあるDBMS_EPGパッケージを使用して埋込みPL/SQLゲートウェイを構成します。

mod_plsqlと比較して、埋込みゲートウェイを使用することのメリットには次のものがあります。

  • Oracle HTTP ServerをインストールせずにApplication ExpressなどのPL/SQL Webアプリケーションを起動できるため、PL/SQLベースのWebアプリケーションのインストール、構成および管理を簡素化できます。

  • 使用されているものと同じ構成手法を使用して、FTPリクエストおよびHTTPリクエストに応じて、Oracle XML DBからコンテンツを提供します。

PL/SQL Webツールキット

このPL/SQLパッケージのセットは、実行時にmod_plsqlによって起動されるストアド・サブプログラムを使用可能にする汎用インタフェースです。

ブラウザのリクエストに対するレスポンスで、PL/SQLサブプログラムはユーザー入力に従ってOracle Databaseのデータを更新または取得します。続いて、ストアド・プロシージャはブラウザに対するHTTPレスポンスを生成します。通常はダウンロード・ファイルまたはHTML表示になります。PL/SQL Web Toolkit APIを使用すると、ストアド・サブプログラムで次のような処理を実行できます。

  • HTTPリクエストの情報の取得

  • コンテンツタイプおよびMIMEタイプなどのHTTPヘッダーの生成

  • ブラウザのCookieの設定

  • HTMLページの生成

表17-1に、一般的に使用されるPL/SQL Web Toolkitパッケージを示します。

表17-1 PL/SQL Web Toolkitで一般的に使用されるパッケージ

パッケージ 内容の説明

HTF

htpパッケージ内のサブプログラムのファンクション・バージョン。ファンクション・バージョンでは、出力がWebページに直接生成されません。かわりに、出力が戻り値として、ファンクションを起動する文に渡されます。ファンクション・コールをネストする必要がある場合、これらのファンクションを使用します。

HTP

HTMLタグを生成するサブプログラム。たとえば、プロシージャhtp.anchorでは、HTMLアンカー・タグ<A>が生成されます。

OWA_CACHE

PL/SQLゲートウェイのキャッシュ機能を使用可能にし、PL/SQL Webアプリケーションのパフォーマンスを向上させるサブプログラム。

このパッケージを使用して、PL/SQLゲートウェイ・ファイル・システムを使用した期限切れベースおよび検証ベースのキャッシュを使用可能にできます。

OWA_COOKIE

クライアントWebブラウザとの間でHTTP Cookieを送受信するサブプログラム。Cookieは、HTTPコール間で状態を保持するためにブラウザで使用される文字列です。状態を保持できるのは、クライアント・セッションの終わりまでか、Cookieの期日が含まれる場合はそれ以上の期間です。

OWA_CUSTOM

Cookieで使用される権限ファンクション。

OWA_IMAGE

ユーザーがイメージをクリックした座標を取得するサブプログラム。宛先リンクによりPL/SQLゲートウェイが起動されるイメージ・マップがある場合、このパッケージを使用します。

OWA_OPT_LOCK

更新内容が失われるのを防ぐために、データベース・コミット時ロック方法を強制実行するサブプログラム。このサブプログラムを使用しないと、あるユーザーが、それまでに別のユーザーによって値が変更されている行を選択して更新しようとした場合、更新内容が失われる場合があります。

OWA_PATTERN

正規表現により、文字列一致検索および文字列操作を実行するサブプログラム。

OWA_SEC

PL/SQLゲートウェイでリクエストの認証に使用されるサブプログラム。

OWA_TEXT

OWA_PATTERNパッケージで文字列の操作に使用されるサブプログラム。直接使用することもできます。

OWA_UTIL

次のタイプのユーティリティ・サブプログラム

  • 動的に生成されたSQLコードによりページを生成する動的SQLユーティリティ。

  • CGI環境変数の値を取得し、URLリダイレクトを実行するHTMLユーティリティ。

  • 正しい日付処理を行うための日付ユーティリティ。日付の値はHTMLでは単純な文字列ですが、Oracle Databaseデータ型として適切に処理される必要があります。

WPG_DOCLOAD

DAD構成を使用して定義したドキュメント・リポジトリからドキュメントをダウンロードするサブプログラム。

関連項目:

PL/SQL Web Toolkitパッケージの構文、説明および例は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。

mod_plsqlゲートウェイを使用したクライアント・リクエストのPL/SQL Webアプリケーションへのマップ

『Oracle HTTP Server mod_plsqlユーザーズ・ガイド』で説明しているように、mod_plsqlは、HTTP上でWebクライアント・リクエストをPL/SQLストアド・サブプログラムにマップします。詳細は、このマニュアルを参照してください。

関連項目:

埋込みPL/SQLゲートウェイの使用

埋込みゲートウェイ機能は、mod_plsqlゲートウェイに類似しています。

トピック:

埋込みPL/SQLゲートウェイによるクライアント・リクエストの処理方法

図17-2に、埋込みゲートウェイによるクライアントHTTPリクエストの処理プロセスを示します。

図17-2 埋込みPL/SQLゲートウェイによるクライアント・リクエストの処理

図17-2の説明が続きます
「図17-2 埋込みPL/SQLゲートウェイによるクライアント・リクエストの処理」の説明

図17-2の各ステップの内容は次のとおりです。

  1. Oracle XML DB HTTP Listenerは、クライアント・ブラウザからのリクエストを受け取り、PL/SQLサブプログラムを起動するようリクエストします。サブプログラムは、PL/SQLに直接記述されたもの、またはPL/SQL Server Pagesがデータベースにアップロードされ、コンパイルされたときに間接的に生成されたものを使用できます。

  2. XML DB HTTP Listenerは、その仮想パス・マッピング構成に指定されているとおり、埋込みPL/SQLゲートウェイにリクエストをルーティングします。

  3. 埋込みゲートウェイではHTTPリクエスト情報およびゲートウェイ構成を使用して、認証にどのデータベース・アカウントを使用するかを決定します。

  4. 埋込みゲートウェイはコール・パラメータを準備して、アプリケーション内でPL/SQLサブプログラムを起動します。

  5. PL/SQLサブプログラムは、リレーショナル・データおよびデータベースからアクセスされたPL/SQL Web ToolkitからHTMLページを生成します。

  6. アプリケーションから埋込みゲートウェイにページを送信します。

  7. 埋込みゲートウェイからXML DB HTTP Listenerにページを送信します。

  8. XML DB HTTP Listenerからクライアント・ブラウザにページを送信します。

mod_plsqlとは異なり、埋込みゲートウェイはOracle XML DB HTTP Listenerを使用してHTTPリクエストを処理します。このリスナーは、Oracle Net Listenerと同じサーバー側プロセスであり、Oracle Net Services、HTTPおよびFTPをサポートします。

XML DBインタフェースを介して一般HTTPリスナー設定を構成します(手順については、『Oracle XML DB開発者ガイド』を参照してください)。Oracle Enterprise Manager Cloud Control (Cloud Control)を使用するか、xdbconfig.xmlファイルを編集することでHTTPリスナーを構成します。DADの属性の作成または設定など、すべての埋込みPL/SQLゲートウェイ構成で、DBMS_EPGパッケージを使用します。

埋込みPL/SQLゲートウェイのインストール

埋込みゲートウェイでは次のコンポーネントが必要です。

  • XML DB HTTP Listener

  • PL/SQL Webツールキット

埋込みPL/SQLゲートウェイは、Oracle XML DBの一部としてインストールします。インストール時、またはDatabase Configuration Assistant(DBCA)によって作成された事前構成済データベースを使用している場合、Oracle XML DBがインストールされ、構成されます。

PL/SQL Web Toolkitはデータベースの標準インストールの一部であるため、追加でインストールする必要はありません。

関連項目:

既存のデータベースにOracle XML DBを手動で追加する方法の詳細は、『Oracle XML DB開発者ガイド』を参照してください。

埋込みPL/SQLゲートウェイの構成

Oracle HTTP Serverの構成ファイルを編集して、mod_plsqlを構成します。埋込みゲートウェイはOracle XML DB HTTP Listenerの一部としてインストールするため、Oracle XML DBサーブレット管理インタフェースを介してサーブレットとして管理します。

埋込みゲートウェイへの構成インタフェースは、PL/SQLパッケージDBMS_EPGです。このパッケージは、XML DBで使用される、基礎となるxdbconfig.xml構成ファイルを変更します。ほとんどのユーザーにとって、埋込みゲートウェイ構成パラメータはデフォルト値で問題ありません。

トピック:

埋込みPL/SQLゲートウェイの構成: 概要

mod_plsqlと同様、PL/SQLストアド・サブプログラムの各リクエストは、データベース・アクセス記述子(DAD)に関連付けられています。DADとは、データベース・アクセスに使用する構成値の集合です。DADでは次のような情報を指定します。

  • 認証に使用するデータベース・アカウント

  • ドキュメントのアップロードおよびダウンロードに使用するサブプログラム

埋込みPL/SQLゲートウェイでは、DADは、XML DB HTTP LISTENER構成のサーブレットとして表されます。各DAD属性は、構成ファイルxdbconfig.xmlのXML要素にマップされます。DAD属性の値は、要素の内容に一致します。たとえば、database-username DAD属性は、<database-username> XML要素に一致し、DAD属性の値がHRである場合、<database-username>HR<database-username>に一致します。DAD属性名は、大/小文字を区別します。

次の埋込みPL/SQLゲートウェイ構成を実行するには、DBMS_EPGパッケージを使用します。

  1. DBMS_EPG.CREATE_DADプロシージャを使用してDADを作成します。
  2. DBMS_EPG.SET_DAD_ATTRIBUTEプロシージャを使用してDAD属性を設定します。

    すべてのDAD属性は、オプションです。属性を指定しない場合は、初期値が使用されます。

表17-2に、埋込みPL/SQLゲートウェイ属性および対応するmod_plsql DADパラメータを示します。「有効な値」の列挙値は大/小文字を区別します。

表17-2 mod_plsql DAD属性と埋込みPL/SQLゲートウェイDAD属性間のマッピング

mod_plsql DAD属性 埋込みPL/SQLゲートウェイDAD属性 重複 有効な値

PlsqlAfterProcedure

after-procedure

なし

文字列

PlsqlAlwaysDescribeProcedure

always-describe-procedure

なし

On、Offの列挙

PlsqlAuthenticationMode

authentication-mode

なし

Basic、SingleSignOn、GlobalOwa、CustomOwa、PerPackageOwaの列挙

PlsqlBeforeProcedure

before-procedure

なし

文字列

PlsqlBindBucketLengths

bind-bucket-lengths

あり

符号なし整数

PlsqlBindBucketWidths

bind-bucket-widths

あり

符号なし整数

PlsqlCGIEnvironmentList

cgi-environment-list

あり

文字列

PlsqlCompatibilityMode

compatibility-mode

なし

符号なし整数

PlsqlDatabaseUsername

database-username

なし

文字列

PlsqlDefaultPage

default-page

なし

文字列

PlsqlDocumentPath

document-path

なし

文字列

PlsqlDocumentProcedure

document-procedure

なし

文字列

PlsqlDocumentTablename

document-table-name

なし

文字列

PlsqlErrorStyle

error-style

なし

ApacheStyle、ModplsqlStyle、DebugStyleの列挙

PlsqlExclusionList

exclusion-list

あり

文字列

PlsqlFetchBufferSize

fetch-buffer-size

なし

符号なし整数

PlsqlInfoLogging

info-logging

なし

Enumeration of InfoDebug

PlsqlInputFilterEnable

input-filter-enable

なし

文字列

PlsqlMaxRequestsPerSession

max-requests-per-session

なし

符号なし整数

PlsqlNLSLanguage

nls-language

なし

文字列

PlsqlOWADebugEnable

owa-debug-enable

なし

On、Offの列挙

PlsqlPathAlias

path-alias

なし

文字列

PlsqlPathAliasProcedure

path-alias-procedure

なし

文字列

PlsqlRequestValidationFunction

request-validation-function

なし

文字列

PlsqlSessionCookieName

session-cookie-name

なし

文字列

PlsqlSessionStateManagement

session-state-management

なし

StatelessWithResetPackageState、StatelessWithFastRestPackageState、StatelessWithPreservePackageStateの列挙

PlsqlTransferMode

transfer-mode

なし

Char、Rawの列挙

PlsqlUploadAsLongRaw

upload-as-long-raw

なし

文字列

埋込みゲートウェイのほとんどのユーザーにとって、DAD属性はデフォルト値で問題ありません。mod_plsqlユーザーには、次の属性は不要です。

  • PlsqlDatabasePassword

  • PlsqlDatabaseConnectString(埋込みゲートウェイで外部データベースへのログオンがサポートされていないため)

DAD属性と同様、グローバル構成パラメータはオプションです。表17-3に、DBMS_EPGグローバル属性および対応するmod_plsqlグローバル・パラメータを示します。

表17-3 mod_plsqlグローバル属性と埋込みPL/SQLゲートウェイ・グローバル属性間のマッピング

mod_plsql DAD属性 埋込みPL/SQLゲートウェイDAD属性 重複 有効な値

PlsqlLogLevel

log-level

なし

符号なし整数

PlsqlMaxParameters

max-parameters

なし

符号なし整数

関連項目:

埋込みPL/SQLゲートウェイのユーザー認証に関する構成

XML DB認証スキームを使用するため、埋込みゲートウェイではデータベースの認証方式がmod_plsqlとは異なります。特に、DADにはデータベースのパスワードは格納されません。

注意:

PL/SQL Webアプリケーションをインターネット上で提供しても、データベースをファイアウォールの内側に保持する場合は、アプリケーションの実行に埋込みPL/SQLゲートウェイを使用せずに、mod_plsqlを使用してください。

データベース認証を構成するには、DBMS_EPGパッケージを使用します。

トピック:

DBMS_EPGによる静的認証の構成

静的認証はデータベースのユーザー名およびパスワードをDADに格納するmod_plsqlユーザー用であるため、ブラウザ・ユーザーがデータベース認証情報を入力する必要はありません。

静的認証を設定するステップは次のとおりです。

  1. XML DB管理者、つまりXDBADMINのロールが割り当てられたユーザーとしてデータベースにログオンします。
  2. DADを作成します。たとえば、次のプロシージャでは、DADによって起動されるHR_DADを作成し、仮想パスを/hrweb/にマップします。
    EXEC DBMS_EPG.CREATE_DAD('HR_DAD', '/hrweb/*');
    
  3. このステップでは、ALTER ANY USERシステム権限が必要です。DADにより権限が使用される必要があるデータベース・アカウントに、DAD属性database-usernameを設定します。たとえば、次のプロシージャでは、DAD名HR_DADHRアカウントの権限を保持すると指定します。
    EXEC DBMS_EPG.SET_DAD_ATTRIBUTE('HR_DAD', 'database-username', 'HR');
    

    DAD属性database-usernameは、大/小文字を区別します。

  4. 前のステップでユーザーが指定したデータベースの権限をDADに割り当てます。この認可によって、エンド・ユーザーはプロシージャを起動し、認可されたアカウントの権限のある埋込みPL/SQLゲートウェイを介してドキュメント表にアクセスできます。例:
    EXEC DBMS_EPG.AUTHORIZE_DAD('HR_DAD', 'HR');
    

    あるいは、XDBADMIN権限のあるユーザーとしてログオフし、その権限がDADで使用される必要があるデータベース・ユーザーとしてログオンしてから、これらの権限をDADに割り当てる次のコマンドを使用します。

    EXEC DBMS_EPG.AUTHORIZE_DAD('HR_DAD');

    注意:

    複数のユーザーが同一のDADを認可できます。DADのdatabase-username属性設定によって、どのユーザーの権限を使用するかが決定されます。

mod_plsqlとは異なり、埋込みゲートウェイは特殊ユーザーANONYMOUSとしてデータベースに接続しますが、データベース・オブジェクトにはDADに割り当てられたユーザー権限でアクセスします。ブラウザ・ユーザーがHTTP Authorizationヘッダーで明示的に接続しようとすると、データベースはアクセスを拒否します。

注意:

アカウントANONYMOUSは、XML DBのインストール後にロックされます。埋込みPL/SQLゲートウェイで静的認証を使用する場合は、最初にこのアカウントのロックを解除します。

DBMS_EPGによる動的認証の構成

動的認証は、DADにデータベースのユーザー名およびパスワードを格納しないmod_plsqlユーザーのためのものです。

動的認証では、データベース・ユーザーは、データベース・オブジェクトへのアクセス権限を使用するため、埋込みゲートウェイを認可する必要がありません。かわりに、ブラウザ・ユーザーがHTTP Basic認証スキーマを介してデータベース認証情報を指定する必要があります。

埋込みゲートウェイのアクションは、DADに対してdatabase-username属性が設定されているかどうかによって異なります。この属性が設定されていない場合、埋込みゲートウェイはブラウザ・クライアントによって指定されたユーザーとして、データベースに接続します。属性が設定されている場合、データベースでは、database-username属性で指定されたユーザーにアクセスを制限します。

動的認証を設定するステップは次のとおりです。

  1. XML DB管理者、つまりXDBADMINのロールのあるユーザーとしてデータベースにログオンします。
  2. DADを作成します。たとえば、次のプロシージャでは、DADによって起動されるDYNAMIC_DADを作成し、仮想パスを/hrweb/にマップします。
    EXEC DBMS_EPG.CREATE_DAD('DYNAMIC_DAD', '/hrweb/*');
    
  3. オプションで、DADにより権限が使用される必要があるデータベース・アカウントに、DAD属性database-usernameを設定します。ブラウザ・ユーザーはDADアクセスの際、このアカウントのユーザー名およびパスワードを入力するよう要求されます。たとえば、次のプロシージャでは、DAD名DYNAMIC_DADHRアカウントの権限を保持すると指定します。
    EXEC DBMS_EPG.SET_DAD_ATTRIBUTE('DYNAMIC_DAD', 'database-username', 'HR');
    

    属性database-usernameは、大/小文字を区別します。

警告:

HTTP Basic認証スキームを介して送信されるパスワードは、暗号化されていません。ブラウザ・クライアントによって送信されるパスワードを保護するため、HTTPSプロトコルを使用するよう埋込みゲートウェイを構成します。

DBMS_EPGによる匿名認証の構成

匿名認証はmod_plsqlユーザー用であり、このユーザーはデータベース・ログオン用の特殊なDADデータベースを作成しますが、アプリケーション・プロシージャおよびドキュメント表を別のスキーマに格納し、プロシージャおよびドキュメント表へのアクセス権をPUBLICに付与します。

匿名認証を設定するステップは次のとおりです。

  1. XML DB管理者、つまりXDBADMINのロールが割り当てられたユーザーとしてデータベースにログオンします。
  2. DADを作成します。たとえば、次のプロシージャでは、DADによって起動されるHR_DADを作成し、仮想パスを/hrweb/にマップします。
    EXEC DBMS_EPG.CREATE_DAD('HR_DAD', '/hrweb/*');
    
  3. DAD属性database-usernameANONYMOUSに設定します。例:
    EXEC DBMS_EPG.SET_DAD_ATTRIBUTE('HR_DAD', 'database-username', 'ANONYMOUS');
    

    database-usernameおよびANONYMOUSはともに、大/小文字を区別します。

    データベース・オブジェクトへのアクセス用ANONYMOUS権限の使用のために埋込みゲートウェイを認可する必要はありません。ANONYMOUSにはシステム権限がなく、データベース・オブジェクトを所有していません。

DADの認証モードの決定

DADの名前がわかっている場合は、このDADの認証モードは次によって決まります。

  • DADが存在するかどうか。

  • database-username属性がDAD用に設定されているかどうか。

  • DADにdatabase-usernameユーザーの権限の使用が認可されているかどうか。

  • database-username属性がDADの使用を認可されているユーザーの名前であるかどうか。

表17-4に、これらの質問の回答に応じた認証モードの決定方法を示します。

表17-4 DADの認証の可能性

DADの有無 database-username設定の有無 ユーザー認可の有無 モード

あり

あり

あり

静的

あり

あり

なし

動的(制限付き)

あり

なし

どちらでもよい

動的

あり

あり(ANONYMOUSに対して)

どちらでもよい

匿名

なし

N/A

たとえば、DAD名MY_DADを作成するとします。MY_DADdatabase-username属性がHRに設定されていても、HRユーザーがMY_DADを認可しない場合、MY_DADの認証モードは制限付きで動的になります。ブラウザ・ユーザーがMY_DADを介してPL/SQLサブプログラムを実行しようとすると、HRデータベースのユーザー名およびパスワードを入力するよう要求されます。

DBA_EPG_DAD_AUTHORIZATIONビューでは、どのユーザーがDADの使用を認可しているかを示します。DAD_NAME列にはDADの名前が表示され、USERNAME列にはDADに権限が割り当てられたユーザーが表示されます。権限が認められたDADは存在しないことがあります。

関連項目:

DBA_EPG_DAD_AUTHORIZATIONビューの詳細は、『Oracle Databaseリファレンス』を参照してください。

例: DADの作成および構成

例17-1では次の処理が行われます。

  • データベース・ユーザーHR用に静的認証のDADを作成し、これを認可するHRアカウントの権限を割り当てます。

  • ユーザーを限定しない、動的認証のDADを作成します。

  • HRアカウントに限定される、動的認証のDADを作成します。

DADの作成および認証は独立しているため、次のことができます。

  • 存在していないDADの認証(後で作成が可能)

  • 自分がユーザーでないDADの認証(ただし、この認証はDAD database-user属性が自分のユーザー名に変更されるまで反映されません)

例17-2では、データベース・ユーザーHR用に静的認証のDADを作成し、これにHRアカウントの権限を割り当てます。その後、次の処理が行われます。

  • データベース・ユーザーHRがそのDADではなく、存在しないDADを認証します。

    ユーザーが誤ってこれを実行した場合でも、存在しないDADは後で作成できるため、エラーは発生しません。

  • データベース・ユーザーOEが、自分のdatabase-user属性がHRに設定されているDADを認証します。

    エラーは発生しませんが、DADのdatabase-user属性がOEに変更されるまで認証は有効になりません。

例17-1 DADの作成および構成

------------------------------------------------------------------------
--- DAD with static authentication
------------------------------------------------------------------------

CONNECT SYSTEM AS SYSDBA
PASSWORD: password
EXEC DBMS_EPG.CREATE_DAD('Static_Auth_DAD', '/static/*');
EXEC DBMS_EPG.SET_DAD_ATTRIBUTE('Static_Auth_DAD', 'database-username', 'HR');
GRANT EXECUTE ON DBMS_EPG TO HR;

-- Authorization
CONNECT HR
PASSWORD: password
EXEC DBMS_EPG.AUTHORIZE_DAD('Static_Auth_DAD');

------------------------------------------------------------------------
-- DAD with dynamic authentication
------------------------------------------------------------------------

CONNECT SYSTEM AS SYSDBA
PASSWORD: password
EXEC DBMS_EPG.CREATE_DAD('Dynamic_Auth_DAD', '/dynamic/*');

-------------------------------------------------------------------------
-- DAD with dynamic authentication restricted
-------------------------------------------------------------------------

EXEC DBMS_EPG.CREATE_DAD('Dynamic_Auth_DAD_Restricted', '/dynamic/*');
EXEC DBMS_EPG.SET_DAD_ATTRIBUTE
  ('Dynamic_Auth_DAD_Restricted', 'database-username', 'HR');

例17-2 後で作成または変更されるDADの認証

REM Create DAD with static authentication for database user HR

CONNECT SYSTEM AS SYSDBA
PASSWORD: password
EXEC DBMS_EPG.CREATE_DAD('Static_Auth_DAD', '/static/*');
EXEC DBMS_EPG.SET_DAD_ATTRIBUTE('Static_Auth_DAD', 'database-username', 'HR');
GRANT EXECUTE ON DBMS_EPG TO HR;

REM Database user HR authorizes DAD that does not exist

CONNECT HR
PASSWORD: password
EXEC DBMS_EPG.AUTHORIZE_DAD('Static_Auth_DAD_Typo');

REM Database user OE authorizes DAD with database-username 'HR'

CONNECT OE
PASSWORD: password
EXEC DBMS_EPG.AUTHORIZE_DAD('Static_Auth_DAD');
例: DADの認証モードの決定

例17-3では、指定されたDADの名称を許容し、その認証モードをレポートするPL/SQLプロシージャshow_dad_auth_statusを作成します。指定したDADが存在しない場合、プロシージャはエラー状態で終了します。

例17-1のスクリプトを実行して、各種DADを作成および構成するとします。出力は次のとおりです。

SET SERVEROUTPUT ON;
BEGIN
  show_dad_auth_status('Static_Auth_DAD');
END;
/
'Static_Auth_DAD' is set up for static authentication for user 'HR'.

例17-3 DADの認証モードの決定

CREATE OR REPLACE PROCEDURE show_dad_auth_status (p_dadname VARCHAR2) IS
  v_daduser VARCHAR2(128);
  v_cnt     PLS_INTEGER;
BEGIN
  -- Determine DAD user
  v_daduser := DBMS_EPG.GET_DAD_ATTRIBUTE(p_dadname, 'database-username');

  -- Determine whether DAD authorization exists for DAD user
  SELECT COUNT(*)
    INTO v_cnt
      FROM DBA_EPG_DAD_AUTHORIZATION da
        WHERE da.DAD_NAME = p_dadname
          AND da.USERNAME = v_daduser;

  -- If DAD authorization exists for DAD user, authentication mode is static
  IF (v_cnt > 0) THEN
    DBMS_OUTPUT.PUT_LINE (
      '''' || p_dadname ||
      ''' is set up for static authentication for user ''' ||
      v_daduser || '''.');
    RETURN;
  END IF;

  -- If no DAD authorization exists for DAD user, authentication mode is dynamic

  -- Determine whether dynamic authentication is restricted to particular user
  IF (v_daduser IS NOT NULL) THEN
    DBMS_OUTPUT.PUT_LINE (
      '''' || p_dadname ||
      ''' is set up for dynamic authentication for user ''' ||
      v_daduser || ''' only.');
  ELSE
    DBMS_OUTPUT.PUT_LINE (
      '''' || p_dadname ||
      ''' is set up for dynamic authentication for any user.');
  END IF;
END;
/
例: すべてのDADの認証モードの決定

例17-4の無名ブロックでは、登録したすべてのDADの認証モードがレポートされます。これによって、例17-3show_dad_auth_statusプロシージャが起動されます。

例17-1のスクリプトを実行して各種DADを作成および構成した場合、例17-4の出力は次のとおりです。

---------- Authorization Status for All DADs ----------
'Static_Auth_DAD' is set up for static auth for user 'HR'.
'Dynamic_Auth_DAD' is set up for dynamic auth for any user.
'Dynamic_Auth_DAD_Restricted' is set up for dynamic auth for user 'HR' only.

例17-4 全DADの認証モードの表示

DECLARE
  v_dad_names DBMS_EPG.VARCHAR2_TABLE;
BEGIN
  DBMS_OUTPUT.PUT_LINE
    ('---------- Authorization Status for All DADs ----------');
  DBMS_EPG.GET_DAD_LIST(v_dad_names);

  FOR i IN 1..v_dad_names.count LOOP
    show_dad_auth_status(v_dad_names(i));
  END LOOP;
END;
/
例: 無効なDAD認可の表示

例17-5の無名ブロックでは、無効なDAD認証がレポートされます。DAD認証は、次の場合は無効です。

  • DADを認可するユーザーが、DADのdatabase-username属性で指定されたユーザーではない。

  • DADを認可するユーザーが存在しない。

例17-2のスクリプトを実行して各種DADを作成および構成した場合、例17-5の出力は次のとおりです(ページ内に収まるように再フォーマット済)。

---------- DAD Authorizations Not in Effect ----------
DAD authorization of 'Static_Auth_DAD' by user 'OE' is not in effect
  because DAD user is 'HR'.
DAD authorization of 'Static_Auth_DAD_Typo' by user 'HR' is not in effect
  because DAD does not exist.

例17-5 無効なDAD認可の表示

DECLARE
  v_dad_names DBMS_EPG.VARCHAR2_TABLE;
  v_dad_user  VARCHAR2(128);
  v_dad_found BOOLEAN;
BEGIN 
  DBMS_OUTPUT.PUT_LINE
    ('---------- DAD Authorizations Not in Effect ----------');
  DBMS_EPG.GET_DAD_LIST(v_dad_names);

  FOR r IN (SELECT * FROM DBA_EPG_DAD_AUTHORIZATION) LOOP  -- Outer loop
    v_dad_found := FALSE;
    FOR i IN 1..v_dad_names.count LOOP  -- Inner loop
      IF (r.DAD_NAME = v_dad_names(i)) THEN
        v_dad_user :=
          DBMS_EPG.GET_DAD_ATTRIBUTE(r.DAD_NAME, 'database-username');

        -- Is database-username the user for whom DAD is authorized?
        IF (r.USERNAME <> v_dad_user) THEN
          DBMS_OUTPUT.PUT_LINE (
            'DAD authorization of ''' || r.dad_name ||
            ''' by user ''' || r.username || '''' ||
            ' is not in effect because DAD user is ' ||
            '''' || v_dad_user || '''.');
        END IF;
        v_dad_found := TRUE;
        EXIT;  -- Inner loop
      END IF;
    END LOOP;  -- Inner loop

    -- Does DAD exist?
    IF (NOT v_dad_found) THEN
      DBMS_OUTPUT.PUT_LINE (
       'DAD authorization of ''' || r.dad_name ||
       ''' by user ''' || r.username ||
       ''' is not in effect because the DAD does not exist.');
    END IF;
  END LOOP;  -- Outer loop
END;
/
埋込みPL/SQLゲートウェイ構成の調査

システム権限のあるユーザーとしてデータベースに接続している場合、次のスクリプトにより、埋込みPL/SQLゲートウェイ構成を調査します。

$ORACLE_HOME/rdbms/admin/epgstat.sql

例17-6に、ANONYMOUSアカウントがロックされている場合の例17-1epgstat.sqlスクリプトの出力を示します。

例17-6 例17-1のepgstat.sqlスクリプトの出力

スクリプトを実行するコマンドは次のとおりです。

@$ORACLE_HOME/rdbms/admin/epgstat.sql

結果:

+--------------------------------------+
| XDB protocol ports:                  |
|  XDB is listening for the protocol   |
|  when the protocol port is nonzero.  |
+--------------------------------------+

HTTP Port FTP Port
--------- --------
        0        0

1 row selected.

+---------------------------+
| DAD virtual-path mappings |
+---------------------------+

Virtual Path                     DAD Name
-------------------------------- --------------------------------
/dynamic/*                       Dynamic_Auth_DAD_Restricted
/static/*                        Static_Auth_DAD

2 rows selected.

+----------------+
| DAD attributes |
+----------------+

DAD Name        DAD Param             DAD Value
------------    --------------------- ----------------------------------------
Dynamic_Auth    database-username     HR
_DAD_Restric
ted

Static_Auth_    database-username     HR
DAD


2 rows selected.

+---------------------------------------------------+
| DAD authorization:                                |
|  To use static authentication of a user in a DAD, |
|  the DAD must be authorized for the user.         |
+---------------------------------------------------+

DAD Name                         User Name
-------------------------------- --------------------------------
Static_Auth_DAD                  HR
                                 OE
Static_Auth_DAD_Typo             HR

3 rows selected.

+----------------------------+
| DAD authentication schemes |
+----------------------------+

DAD Name             User Name                        Auth Scheme
-------------------- -------------------------------- ------------------
Dynamic_Auth_DAD                                      Dynamic
Dynamic_Auth_DAD_Res HR                               Dynamic Restricted
tricted

Static_Auth_DAD      HR                               Static

3 rows selected.

+--------------------------------------------------------+
| ANONYMOUS user status:                                 |
|  To use static or anonymous authentication in any DAD, |
|  the ANONYMOUS account must be unlocked.               |
+--------------------------------------------------------+

Database User   Status
--------------- --------------------
ANONYMOUS       EXPIRED & LOCKED

1 row selected.

+-------------------------------------------------------------------+
| ANONYMOUS access to XDB repository:                               |
|  To allow public access to XDB repository without authentication, |
|  ANONYMOUS access to the repository must be allowed.              |
+-------------------------------------------------------------------+

Allow repository anonymous access?
----------------------------------
false

1 row selected.

埋込みPL/SQLゲートウェイを介したPL/SQLストアド・サブプログラムの起動

埋込みPL/SQLゲートウェイを介してPL/SQLサブプログラムを起動する基本ステップは、mod_plsqlゲートウェイに対するものと同じです。詳細は、『Oracle HTTP Server mod_plsqlユーザーズ・ガイド』を参照してください。mod_plsql命令は埋込みゲートウェイで使用するため、若干の調整が必要です。たとえば、次の形式でURLを入力し、ブラウザで埋込みゲートウェイを起動します。

protocol://hostname[:port]/virt-path/[[!][schema.][package.]proc_name[?query_str]]

プレースホルダvirt-pathは、DBMS_EPG.CREATE_DADで構成する仮想パスを表します。mod_plsqlのドキュメントでは、virt-pathのかわりにDAD_locationを使用します。

関連項目:

  • 次のトピックについては、『Oracle HTTP Server mod_plsqlユーザーズ・ガイド』を参照してください。

    • トランザクション・モード

    • サポートされるデータ型

    • パラメータ渡しのスキーム

    • ファイルのアップロード/ダウンロードのサポート

    • パスの別名

    • Common Gateway Interface(CGI)環境変数

埋込みPL/SQLゲートウェイによるアプリケーション・アクセスの保護

埋込みゲートウェイは、mod_plsqlと同じ保護メカニズムを使用します。

埋込みPL/SQLゲートウェイの制限事項

mod_plsqlの制限は、埋込みゲートウェイにも同様に適用されます。また、ゲートウェイの埋込みバージョンでは、次の機能はサポートされません。

  • 動的HTMLキャッシング

  • システムの監視

  • Basic以外の認証モード

関連項目:

埋込みPL/SQLゲートウェイの使用: 使用例

この項では、hr.employees表に対して問合せを行い、PL/SQLゲートウェイを介してWebブラウザにHTML出力を供給する簡易アプリケーションを作成する方法について説明します。XML DBおよびサンプル・スキーマの両方がインストールされているものとします。

プログラムを作成して実行するステップは次のとおりです。

  1. ALTER USER権限のあるユーザーとしてデータベースにログオンし、データベース・アカウントANONYMOUSのロックが解除されていることを確認します。ANONYMOUSアカウントはデフォルトでロックされており、静的認証を必要とします。アカウントがロックされている場合は、次のSQL文を使用してそのロックを解除します。
    ALTER USER anonymous ACCOUNT UNLOCK;
    
  2. XML DB管理者、つまりXDBADMINのロールのあるユーザーとしてデータベースにログオンします。

    データ・ディクショナリを問い合せ、どのユーザーおよびロールにXDADMINのロールが付与されているかを確認します。

    SELECT *
    FROM DBA_ROLE_PRIVS
    WHERE GRANTED_ROLE = 'XDBADMIN';
    
  3. DADを作成します。たとえば、次のプロシージャでは、DADによって起動されるHR_DADを作成し、仮想パスを/plsql/にマップします。
    EXEC DBMS_EPG.CREATE_DAD('HR_DAD', '/plsql/*');
    
  4. DADにより権限が使用される必要があるデータベース・ユーザーに、DAD属性database-usernameを設定します。たとえば、次のプロシージャでは、DAD HR_DADがユーザーHR権限によってデータベース・オブジェクトにアクセスすることを指定します。
    EXEC DBMS_EPG.SET_DAD_ATTRIBUTE('HR_DAD', 'database-username', 'HR');
    

    属性database-usernameは、大/小文字を区別します。

  5. DADにより権限が使用される必要のあるデータベース・ユーザーにEXECUTE権限を付与します(これによって、ユーザーはDADを認証できます)。例:
    GRANT EXECUTE ON DBMS_EPG TO HR;
    
  6. XML DB管理者としてログオフし、DADにより権限が使用される必要があるデータベース・ユーザーとして、データベースにログオンします(例: HR)。
  7. 埋込みPL/SQLゲートウェイを認可してプロシージャを起動し、DADを介してドキュメント表にアクセスします。例:
    EXEC DBMS_EPG.AUTHORIZE_DAD('HR_DAD');
    
  8. サンプルのPL/SQLストアド・プロシージャによって起動されるprint_employeesを作成します。次のプログラムでは、hr.employeesの問合せの結果セットを含むHTMLページを作成します。
    CREATE OR REPLACE PROCEDURE print_employees IS
      CURSOR emp_cursor IS
        SELECT last_name, first_name
          FROM hr.employees
            ORDER BY last_name;
    BEGIN
      HTP.PRINT('<html>');
      HTP.PRINT('<head>');
      HTP.PRINT('<meta http-equiv="Content-Type" content="text/html">');
      HTP.PRINT('<title>List of Employees</title>');
      HTP.PRINT('</head>'); 
      HTP.PRINT('<body TEXT="#000000" BGCOLOR="#FFFFFF">');
      HTP.PRINT('<h1>List of Employees</h1>');
      HTP.PRINT('<table width="40%" border="1">');
      HTP.PRINT('<tr>');
      HTP.PRINT('<th align="left">Last Name</th>');
      HTP.PRINT('<th align="left">First Name</th>');
      HTP.PRINT('</tr>');
      FOR emp_record IN emp_cursor LOOP
        HTP.PRINT('<tr>');
        HTP.PRINT('<td>' || emp_record.last_name  || '</td>');
        HTP.PRINT('<td>' || emp_record.first_name || '</td>');
      END LOOP;
      HTP.PRINT('</table>');
      HTP.PRINT('</body>');
      HTP.PRINT('</html>');
    END;
    /
    
  9. Oracle NetリスナーがHTTPリクエストを受け入れられることを確認します。システム・プロンプトで次のコマンドを実行して、LinuxおよびUNIXでのリスナーのステータスを確認できます。
    lsnrctl status | grep HTTP
    

    出力は次のとおりです(ページ・サイズによる制限のため単一行から複数行に再フォーマット済)。

    (DESCRIPTION=
      (ADDRESS=(PROTOCOL=tcp)(HOST=example.com)(PORT=8080))
      (Presentation=HTTP)
      (Session=RAW)
    )
    

    HTTPサービスが起動していないことを確認できた場合は、初期化パラメータ・ファイルに次の行を追加(listener_nameにOracle Netローカル・リスナーを指定)し、データベースおよびリスナーを再起動します。

    dispatchers="(PROTOCOL=TCP)"
    local_listener=listener_name
    
  10. Webブラウザからprint_employeesプログラムを実行します。たとえば、hostに自分のホスト・コンピュータ名を指定し、portに前のステップのPORTの値を指定すると、次のURLを使用できます。
    http://host:port/plsql/print_employees
    

    たとえば、ホストがtest.comで、HTTPポートが8080である場合は、次のように入力します。

    http://example.com:8080/plsql/print_employees
    

    Webブラウザに、hr.employees表に全従業員の姓名が記載された表のあるHTMLページが戻されます。

PL/SQLを使用したHTML出力の生成

一般的に、PL/SQL Webアプリケーションでは、ファンクション・コールを使用して出力用の各HTMLタグを生成します。このファンクションは、Oracle Databaseに付属するPL/SQL Web Toolkitパッケージの一部です。例17-7に、各HTMLタグと対応するHTPファンクションをコールして簡単なHTMLページを生成する方法を示します。

各タグに対応するファンクション・コールを作成するかわりに、HTP.PRINTファンクションを使用して、テキストとタグを両方とも出力します。例17-8に、その方法を示します。

例17-7 HTPファンクションを使用したHTMLタグの生成

CREATE OR REPLACE PROCEDURE html_page IS
BEGIN
  HTP.HTMLOPEN;                            -- generates <HTML>
  HTP.HEADOPEN;                            -- generates <HEAD>
  HTP.TITLE('Title');                      -- generates <TITLE>Hello</TITLE>
  HTP.HEADCLOSE;                           -- generates </HTML> 

  -- generates <BODY TEXT="#000000" BGCOLOR="#FFFFFF">
  HTP.BODYOPEN( cattributes => 'TEXT="#000000" BGCOLOR="#FFFFFF"');

  -- generates <H1>Heading in the HTML File</H1>
  HTP.HEADER(1, 'Heading in the HTML File');

  HTP.PARA;                                 -- generates <P>        
  HTP.PRINT('Some text in the HTML file.'); 
  HTP.BODYCLOSE;                            -- generates </BODY>
  HTP.HTMLCLOSE;                            -- generates </HTML>
END;
/

例17-8 HTP.PRINTを使用したHTMLタグの生成

CREATE OR REPLACE PROCEDURE html_page2 IS
BEGIN
  HTP.PRINT('<html>');
  HTP.PRINT('<head>');
  HTP.PRINT('<meta http-equiv="Content-Type" content="text/html">');
  HTP.PRINT('<title>Title of the HTML File</title>');
  HTP.PRINT('</head>');
  HTP.PRINT('<body TEXT="#000000" BGCOLOR="#FFFFFF">');
  HTP.PRINT('<h1>Heading in the HTML File</h1>');
  HTP.PRINT('<p>Some text in the HTML file.');
  HTP.PRINT('</body>');
  HTP.PRINT('</html>');
END;
/

PL/SQL Webアプリケーションへのパラメータ渡し

Webアプリケーションを様々な状況で有効に活用するには、対話性を十分に高め、ユーザーによる選択を可能にする必要があります。迅速さを求めるWeb閲覧者に対応するには、対話の効率をよくし、ユーザーが選択項目を簡単に指定できるように、過多な決定事項やデータ入力を避ける必要があります。

PL/SQL Webアプリケーションにパラメータを渡す主な方法は、次のとおりです。

  • HTMLフォーム・タグを使用します。ユーザーが1つのWebページ上のフォームに記入して、「Submit」ボタンをクリックすると、すべてのデータおよび選択項目がストアド・サブプログラムに転送されます。

  • URLにハードコード化します。ユーザーがリンクをクリックすると、一連の事前定義パラメータがストアド・サブプログラムに転送されます。通常、ユーザーが選択する可能性があるすべての選択項目には、Webページ上に個別のリンクを挿入します。

トピック:

HTMLフォームからのリスト・パラメータおよびドロップダウン・リスト・パラメータ渡し

リスト・ボックスおよびドロップダウン・リストは、HTMLタグ(<SELECT>)を使用して実装されます。

選択項目の数を多くする、または複数の選択を可能にする必要がある場合は、リスト・ボックスを使用します。リスト・ボックスは、項目をアルファベット順に表示する場合に適しています。これによって、ユーザーは、すべての項目を読まなくても目的の項目を短時間で検索できます。

次の場合にドロップダウン・リストを使用します。

  • 選択項目が少ない

  • 画面のスペースがかぎられている。

  • 選択項目の順序が特殊。

ドロップダウン・リストは、初めてアクセスするユーザーの注意を引き、選択項目を読ませることができます。選択項目および順序を固定することで、ユーザーはドロップダウン・リストから項目を選択するときの動作に慣れ、素早く選択できるようになります。

例17-9に、簡単なドロップダウン・リストを示します。

例17-9 HTMLドロップダウン・リスト

<form>
<select name="seasons">
<option value="winter">Winter
<option value="spring">Spring
<option value="summer">Summer
<option value="fall">Fall
</select>

HTMLフォームからのオプション・パラメータおよびチェック・ボックス・パラメータ渡し

オプション・ボタンによって、NULL値(グループ内のいずれのオプションもチェックされていない場合)、またはチェックされたオプションに指定されている値のいずれかが渡されます。

一連のオプションのデフォルト値を指定するには、INPUTタグにCHECKED属性を含めるか、ストアド・サブプログラム内のパラメータにDEFAULT句を含めます。オプションのグループを設定するときは、「どちらでもない」ことを示す選択項目を含める必要があります。これは、オプションを選択した後では、別のボタンを選択することはできますが、選択を完全に取り消すことができないためです。たとえば、あるユーザーが選択を行った後に、それが間違っていたことに気付くという状況を考慮して、「はい」および「いいえ」とともに「興味なし」または「わからない」という選択項目を含めます。

チェック・ボックスでは、ストアド・サブプログラムがNULL値、単一の値、または複数の値を受け取る場合があるため、特別な処理が必要です。

同じNAME属性を持つチェック・ボックスはすべて、チェック・ボックス・グループを構成します。グループ内のいずれのチェック・ボックスもチェックされていない場合、ストアド・サブプログラムは、対応するパラメータに対してNULL値を受け取ります。

グループ内のチェック・ボックスの1つがチェックされている場合、ストアド・サブプログラムは単一のVARCHAR2パラメータを受け取ります。

グループ内の複数のチェック・ボックスがチェックされている場合、ストアド・サブプログラムはPL/SQLのTABLE OF VARCHAR2データ型のパラメータを受け取ります。TABLE OF VARCHAR2のようなデータ型を宣言するか、OWA_UTIL.IDENT_ARRのような事前定義のデータ型を使用する必要があります。値を検索するには、次のようにループを使用します。

CREATE OR REPLACE PROCEDURE handle_checkboxes (
  checkboxes owa_util.ident_arr
) AS
BEGIN
  FOR i IN 1..checkboxes.count
  LOOP
    htp.print('<p>Check Box value: ' || checkboxes(i));
  END LOOP;
END;
/

HTMLフォームからの入力フィールド・パラメータ渡し

入力フィールドでは、ユーザーが誤った形式のデータや範囲外のデータなどを入力する可能性があるため、最も厳密な妥当性チェックが必要です。可能な場合、クライアント側JavaScript関数を使用してクライアント側でデータの妥当性チェックを行い、ユーザーにかわって正しいフォーマットにするか、ユーザーに再入力を促します。

例:

  • ユーザーが数値入力フィールドにアルファベット文字を入力したり、文字数制限を超えた後に文字を入力することができないようにします。

  • クレジット・カード番号から空白およびハイフンを暗黙的に削除します(ストアド・サブプログラムでこの形式の値が要求されている場合)。

  • ユーザーが最大値を超える数値を入力した場合、すぐに通知して、ユーザーに再入力を促します。

これらの妥当性チェックが成功するとはかぎらないため、このような状況に対応できるようにストアド・サブプログラムをコーディングします。ユーザーが誤ったデータを入力したときに「Back」ボタンを押さなくて済むように、エラー・メッセージと他のすべての値が記入された元のフォームを、1つのページに表示します。

パスワードなどの機密性の高い情報の場合、入力フィールドの<INPUT TYPE=PASSWORD>という特殊なフォームによって、入力されたテキストが非表示になります。

例17-10のプロシージャは、入力として2つの文字列を受け入れます。このプロシージャが初めて起動された場合、値を入力するための単純なフォームのプロンプトが表示されます。ユーザーが情報を送ると、同じプロシージャが再起動され、入力が正しいかどうかが確認されます。入力が正しい場合、プロシージャは入力を処理します。正しくない場合、プロシージャは、再入力するためのプロンプトを、最初の値が入力された状態で表示します。

例17-10 HTMLフォームからの入力フィールド・パラメータ渡し

DROP TABLE name_zip_table;
CREATE TABLE name_zip_table (
  name     VARCHAR2(100),
  zipcode  NUMBER
);

-- Store a name and associated zip code in the database.

CREATE OR REPLACE PROCEDURE associate_name_with_zipcode
  (name VARCHAR2 := NULL,
   zip  VARCHAR2 := NULL)
AS
BEGIN
  -- Each entry field must contain a value. Zip code must be 6 characters.
  -- (In a real program you perform more extensive checking.)

  IF name IS NOT NULL AND zip IS NOT NULL AND length(zip) = 6 THEN
    INSERT INTO name_zip_table (name, zipcode) VALUES (name, zip);

    HTP.PRINT('<p>The person ' || HTP.ESCAPE_SC(name) ||
              ' has the zip code ' || HTP.ESCAPE_SC(zip) || '.');

    -- If input was OK, stop here. User does not see form again.
    RETURN;
  END IF;

  -- If user entered incomplete or incorrect data, show error message.

  IF (name IS NULL AND zip IS NOT NULL)
    OR (name IS NOT NULL AND zip IS NULL)
      OR (zip IS NOT NULL AND length(zip) != 6)
  THEN
    HTP.PRINT('<p><b>Please reenter data. Fill all fields,
               and use 6-digit zip code.</b>');
  END IF;

  -- If user entered no data or incorrect data, show error message
  -- & make form invoke same procedure to check input values.

  HTP.FORMOPEN('HR.associate_name_with_zipcode', 'GET');
  HTP.PRINT('<p>Enter your name:</td>');

  HTP.PRINT('<td valign=center><input type=text name=name value="' ||
            HTP.ESCAPE_SC(name) || '">');

  HTP.PRINT('<p>Enter your zip code:</td>');

  HTP.PRINT('<td valign=center><input type=text name=zip value="' ||
            HTP.ESCAPE_SC(zip) || '">');

  HTP.FORMSUBMIT(NULL, 'Submit');
  HTP.FORMCLOSE;
END;
/

HTMLフォームからの非表示パラメータ渡し

ユーザーが同じ選択項目を毎回指定しなくても、一連のストアド・サブプログラムを介して情報を渡すには、ストアド・サブプログラムを起動するフォームに非表示パラメータを含める方法があります。最初のストアド・サブプログラムによって、このストアド・サブプログラムで生成されたHTMLフォームにユーザー名などの情報が入力されます。非表示パラメータの値は、ユーザーがその値をオプションまたは入力フィールドを介して入力した場合と同様に、次のストアド・サブプログラムに渡されます。

1つのストアド・サブプログラムから別のサブプログラムに情報を渡すには、次の方法もあります。

  • 永続情報を含む「Cookie」をブラウザに送信します。ブラウザは、同じサイトから他のWebページにアクセスするときに、同じ情報をサーバーに戻します。Cookieは、各WebページのHTMLテキストの前に、ブラウザとWebサーバーの間で転送されるHTTPヘッダーを介して設定され、検索されます。

  • データベース自体に情報を格納し、後でストアド・サブプログラムが検索できるようにします。この方法ではデータベース・サーバーに余分なオーバーヘッドが発生し、複数のユーザーがサーバーに同時アクセスしたときに、各ユーザーを追跡する方法を見つける必要があります。

HTMLフォームからのファイルのアップロード

HTMLフォームを使用して、クライアント・システム上のファイルを選択し、これをサーバーに転送できます。ストアド・サブプログラムにより、CLOBBLOBまたは大量のデータを保持できるその他のデータ型として、データベースにファイルを挿入できます。

PL/SQL Web ToolkitおよびPL/SQLゲートウェイには、アップロードされたファイルを保持する「ドキュメント表」の概念があります。

関連項目:

『mod_plsqlユーザーズ・ガイド』

記入済HTMLフォームの送信

デフォルトでは、HTMLフォームには、データをHTMLフォームからストアド・サブプログラムまたはCGIプログラムに転送するための送信(Submit)ボタンが必要です。このボタンには、「検索」や「登録」など任意の名前を指定できます。

1つのページに複数のフォームを挿入し、各フォームに独自のフォーム要素と送信(Submit)ボタンを設定できます。非表示パラメータのみで構成されるフォームも作成できます。このフォームでは、ユーザーはボタンをクリックする以外の選択は行いません。

JavaScriptなどのスクリプト言語を使用すると、送信ボタンを削除して、ドロップダウン・リストからの選択など、別のアクションに応答してフォームが送られるようにすることができます。この方法は、ユーザーが選択する項目が1つで、送信(Submit)ボタンで確認するステップが必要でない場合に最適です。

HTMLフォームの欠落した入力の処理

HTMLフォームが送られると、ストアド・サブプログラムは、記入されていないフォーム要素に対してNULLパラメータを受け取ります。NULLパラメータの原因には、入力フィールドが空である、一連のチェック・ボックス、オプションまたはリスト項目がチェックされていない、またはVALUEパラメータの値が""(空の引用符)である、などがあります。

クライアント側で実行する妥当性チェックの内容にかかわらず、ストアド・サブプログラムのコードを使用して、いくつかのパラメータがNULLになる状況に対処します。

  • すべてのパラメータ宣言に初期値を指定して、フォーム・パラメータが欠落した状態でストアド・サブプログラムが起動されたときに発生する例外を回避します。数値に対する初期値は0(ゼロ)に設定できます(適切な場合)。ユーザーが値を指定したかどうか確認するには、NULLを使用します。

  • 初期値NULLを持つ入力パラメータ値を使用する前に、その値がNULLかどうかを確認します。

  • 一部の入力パラメータが指定されていないときでも、サブプログラムが有効な結果を生成するようにします。レポートから一部のセクションを除外するか、パラメータが指定されていない場所を示すテキスト文字列またはイメージをレポート内に表示します。

  • 欠落している値を結果ページから直接入力することで、ストアド・サブプログラムを再実行できるようにします。たとえば、追加パラメータを指定して同じストアド・サブプログラムを起動するリンクを含めたり、出力の一部として値を挿入して元のフォームを表示させることができます。

Webページ間での状態情報の保持

Webアプリケーションでは、状態(特定の時点における現行のデータ・セット)の概念が特に重要です。Webページを切り替えると状態情報が簡単に失われ、ユーザーに何度も同じ選択をさせることになる場合があります。

状態情報は、HTMLフォームを使用して動的Webページ間で渡されます。情報は一連の名前/値ペアとして渡され、ストアド・サブプログラムのパラメータになります。

ユーザーが複数の選択をする必要がある場合、多くの選択項目から1つを選択する必要がある場合、または偶然に誤って選択することを回避することが重要な場合は、HTMLフォームを使用します。ユーザーは、すべての選択を行って、選択した項目を再確認すると、「Submit」ボタンを押して選択を決定します。それ以降のページでは、非表示パラメータ(<INPUT TYPE=HIDDEN>タグ)を含むフォームを使用して、これらの選択項目をページからページへと渡すことができます。

ユーザーが1つまたは2つの選択項目に関心がある場合、または選択事項がWebページ内に散在している場合、アクションをハイパーリンクとして表し、必要な名前/値ペアを問合せ文字列(URL内の「?」の後に続く部分)に含めることによって、ユーザーが送信(Submit)ボタンを簡単に見つけられるようにできます。

状態情報は、Oracle Application Serverおよびそのmod_oseモジュールを使用して保持することもできます。この方法では、状態情報をパッケージ変数に格納して、ユーザーがWebサイトを移動しても、情報を使用可能のままにできます。

関連項目:

Oracle Application Serverのマニュアル・セット:

http://www.oracle.com/technetwork/indexes/documentation/index.html

PL/SQLサブプログラムでのネットワーク操作の実行

OracleはPL/SQLサブプログラムがPL/SQLを使用してネットワーク操作のセットを実行できるようにするパッケージを提供します(電子メールの送信、ホスト名またはアドレスの取得、TCP/IP接続の使用、HTTP URLコンテンツの取得、および表、イメージ・マップ、Cookie、CGI変数の使用)。

Internet Protocol Version 6(IPv6)のサポート

Oracle Database 11gリリース2(11.2.0.1)では、PL/SQLネットワーク・ユーティリティ・パッケージがIPv6アドレスをサポートします。

パッケージ・インタフェースは変更されていません。ネットワーク・ホストを指定できるすべてのインタフェース・パラメータはIPv6アドレスを文字列形式で受け入れ、IPアドレスを返すすべてのインタフェースはIPv6アドレスを返します。

ただし、ネットワーク・アドレスを使用するアプリケーションでは、IPv6アドレスを処理するために、わずかな変更と再コンパイルが必要になる場合があります。IPv6アドレスは128ビットですが、IPv4アドレスは32ビットです。IPv6アドレスは、URL内では大カッコで囲む必要があります。例:

http://[2001:0db8:85a3:08d3:1319:8a2e:0370:7344]/

関連項目:

PL/SQLからの電子メールの送信

例17-11のように、PL/SQLサブプログラムはUTL_SMTPパッケージを使用して電子メールを送信できます。

関連項目:

UTL_SMTPパッケージの詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。

例17-11 PL/SQLからの電子メールの送信

CREATE OR REPLACE PROCEDURE send_test_message
IS
  mailhost   VARCHAR2(64) := 'mailhost.example.com';
  sender     VARCHAR2(64) := 'me@example.com';
  recipient  VARCHAR2(64) := 'you@example.com';
  mail_conn  UTL_SMTP.CONNECTION;
BEGIN
  mail_conn := UTL_SMTP.OPEN_CONNECTION(mailhost, 25); -- 25 is the port
  UTL_SMTP.HELO(mail_conn, mailhost);
  UTL_SMTP.MAIL(mail_conn, sender);
  UTL_SMTP.RCPT(mail_conn, recipient);
 
  UTL_SMTP.OPEN_DATA(mail_conn);
  UTL_SMTP.WRITE_DATA(mail_conn, 'This is a test message.' || chr(13));
  UTL_SMTP.WRITE_DATA(mail_conn, 'This is line 2.' || chr(13));
  UTL_SMTP.CLOSE_DATA(mail_conn);
 
  /* If message were in single string, open_data(), write_data(),
     and close_data() could be in a single call to data(). */
 
  UTL_SMTP.QUIT(mail_conn);
EXCEPTION
  WHEN OTHERS THEN
   -- Insert error-handling code here
   RAISE;
END;
/

PL/SQLからのホスト名またはアドレスの取得

PL/SQLサブプログラムは、UTL_INADDRパッケージを使用して、ローカル・システムのホスト名または特定のホスト名のIPアドレスを判別できます。

関連項目:

UTL_INADDRパッケージの詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。

PL/SQLからのTCP/IP接続の使用

PL/SQLサブプログラムは、UTL_TCPパッケージを使用して、ネットワーク上のシステムにTCP/IP接続をオープンし、対応するソケットへの読込みまたは書込みを行います。

関連項目:

UTL_TCPパッケージの詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。

PL/SQLからのHTTP URLコンテンツの取得

PL/SQLサブプログラムは、UTL_HTTPパッケージを使用して次の操作を実行できます。

  • HTTP URLのコンテンツの取得

    通常、コンテンツはHTMLタグ・テキストの形式ですが、Webサーバーからダウンロード可能な種類のファイル(たとえば、プレーン・テキストまたはJPEGイメージ)であることもあります。

  • HTTPセッションの詳細(ヘッダー、cookie、リダイレクト、プロキシ・サーバー、保護サイトのIDとパスワード、CGIパラメータなど)の管理

  • HTTP 1.1永続接続を使用した同じWebサイトへの同時アクセスの高速化

PL/SQLサブプログラムは、ファンクションUTL_URL.ESCAPEUTL_URL.UNESCAPEを使用して、UTL_HTTPパッケージで使用するためにURLの構築と解釈を行うことができます。

例17-12のPL/SQLプロシージャは、UTL_HTTPパッケージを使用してHTTP URLのコンテンツを取得します。

次のブロックでは、例17-12のプロシージャのコールの例を示していますが、そのURLは存在しないページのものです。自分のWebブラウザからURLを代入します。

BEGIN
  show_url('http://www.oracle.com/no-such-page.html');
  show_url('http://www.oracle.com/protected-page.html');
  show_url
    ('http://www.oracle.com/protected-page.html','username','password');
END;
/

関連項目:

例17-12 PL/SQLからのHTTP URLコンテンツの取得

CREATE OR REPLACE PROCEDURE show_url
  (url      IN VARCHAR2,
  username IN VARCHAR2 := NULL,
  password IN VARCHAR2 := NULL)
AS
  req        UTL_HTTP.REQ;
  resp       UTL_HTTP.RESP;
  name_      VARCHAR2(256);
  value_     VARCHAR2(1024);
  data_      VARCHAR2(255);
  my_scheme  VARCHAR2(256);
  my_realm   VARCHAR2(256);
  my_proxy   BOOLEAN;
BEGIN
  -- When going through a firewall, pass requests through this host.
  -- Specify sites inside the firewall that do not need the proxy host.
 
  UTL_HTTP.SET_PROXY('proxy.example.com', 'corp.example.com');
 
  -- Ask UTL_HTTP not to raise an exception for 4xx and 5xx status codes,
  -- rather than just returning the text of the error page.
 
  UTL_HTTP.SET_RESPONSE_ERROR_CHECK(FALSE);
 
  -- Begin retrieving this web page.
 req := UTL_HTTP.BEGIN_REQUEST(url);
 
  -- Identify yourself.
  --  Some sites serve special pages for particular browsers.
  UTL_HTTP.SET_HEADER(req, 'User-Agent', 'Mozilla/4.0');
 
  -- Specify user ID and password for pages that require them.
  IF (username IS NOT NULL) THEN
    UTL_HTTP.SET_AUTHENTICATION(req, username, password);
  END IF;
 
  -- Start receiving the HTML text.
  resp := UTL_HTTP.GET_RESPONSE(req);
 
  -- Show status codes and reason phrase of response.
  DBMS_OUTPUT.PUT_LINE('HTTP response status code: ' || resp.status_code);
  DBMS_OUTPUT.PUT_LINE
    ('HTTP response reason phrase: ' || resp.reason_phrase);
 
  -- Look for client-side error and report it.
  IF (resp.status_code >= 400) AND (resp.status_code <= 499) THEN
 
  -- Detect whether page is password protected
  -- and you didn't supply the right authorization.
 
  IF (resp.status_code = UTL_HTTP.HTTP_UNAUTHORIZED) THEN
  UTL_HTTP.GET_AUTHENTICATION(resp, my_scheme, my_realm, my_proxy);
  IF (my_proxy) THEN
    DBMS_OUTPUT.PUT_LINE('Web proxy server is protected.');
    DBMS_OUTPUT.PUT('Please supply the required ' || my_scheme ||
      ' authentication username for realm ' || my_realm ||
      ' for the proxy server.');
  ELSE
    DBMS_OUTPUT.PUT_LINE('Web page ' || url || ' is protected.');
    DBMS_OUTPUT.PUT('Please supplied the required ' || my_scheme ||
      ' authentication username for realm ' || my_realm ||
      ' for the web page.');
  END IF;
  ELSE
    DBMS_OUTPUT.PUT_LINE('Check the URL.');
  END IF;
 
  UTL_HTTP.END_RESPONSE(resp);
    RETURN;
 
  -- Look for server-side error and report it.
  ELSIF (resp.status_code >= 500) AND (resp.status_code <= 599) THEN
    DBMS_OUTPUT.PUT_LINE('Check if the website is up.');
    UTL_HTTP.END_RESPONSE(resp);
    RETURN;
  END IF;
 
  -- HTTP header lines contain information about cookies, character sets,
  -- and other data that client and server can use to customize each
  -- session.
 
  FOR i IN 1..UTL_HTTP.GET_HEADER_COUNT(resp) LOOP
    UTL_HTTP.GET_HEADER(resp, i, name_, value_);
    DBMS_OUTPUT.PUT_LINE(name_ || ': ' || value_);
  END LOOP;
 
  -- Read lines until none are left and an exception is raised.
  LOOP
    UTL_HTTP.READ_LINE(resp, value_);
    DBMS_OUTPUT.PUT_LINE(value_);
  END LOOP;
EXCEPTION
  WHEN UTL_HTTP.END_OF_BODY THEN
  UTL_HTTP.END_RESPONSE(resp);
END;
/

PL/SQLからの表、イメージ・マップ、Cookie、およびCGI変数の使用

PL/SQLサブプログラムは、Oracle提供のパッケージやOracle HTTP Server(OHS)のmod_plsqlプラグインを使用して、問合せ結果のHTML表としての書式設定、イメージ・マップの生成、HTTP cookieの取得、CGI変数の値の確認、その他の一般的なWeb操作の実行を行います。

これらのパッケージのドキュメントは、データベース・ドキュメント・ライブラリの一部ではありません。ドキュメントの場所は、アプリケーション・サーバーによって異なります。これらのパッケージを使用するには、次に示すSQL*PlusのDESCRIBE文を使用して、サブプログラム名およびパラメータを確認します。

DESCRIBE HTP;
DESCRIBE HTF;
DESCRIBE OWA_UTIL;