4 Oracle REST Data Servicesアプリケーションの開発
注意:
すぐに開始する場合は、『Oracle REST Data Servicesクイック・スタート・ガイド』のチュートリアルを試すことができます。ただし、後でこの章に戻り、主要な概念と技術を理解してください。
注意:
チュートリアルおよび例を試してみる前に、Oracle Application Express 4.2以上およびOracle REST Data Services 3.0以上の両方がインストールされ、構成されていることを確認してください。
JSONデータの永続にOracle REST APIを使用する場合は、まずOracle REST APIをインストールする必要があります。詳細は、『Oracle REST Data Services SODA for REST開発者ガイド』のOracle REST APIのインストールに関する項を参照してください。
読者はOracle Application Expressに精通していることを前提としています。Oracle Application Expressを初めて使用する場合は、Oracle Application Expressのドキュメントを参照してください。
トピック:
また、補足的な拡張例として、アプリケーションの構築にOracle Application Expressを使用する「イメージ・ギャラリの作成」を確認することもできます。
4.1 関連するソフトウェアの紹介
この項では、Oracle REST Data Servicesを使用するアプリケーションを開発するための、いくつかの重要な関連ソフトウェアについて説明します。
トピック:
4.1.1 Oracle Application Expressについて
Oracle Application Expressは、Oracleデータベースのための宣言型のラピッドWebアプリケーション開発ツールです。これは、完全にサポートされている、Oracleデータベースのすべてのエディションで利用可能なコスト不要のオプションです。Webブラウザのみを使用して、高速でセキュアなプロフェッショナル・アプリケーションを開発し、デプロイできます。
4.1.2 RESTful Webサービスについて
Representational State Transfer (REST)は、World Wide Webのような分散ハイパーメディア・システムのためのソフトウェア・アーキテクチャのスタイルです。APIは、RESTの原則に適合する場合にRESTfulと称されます。RESTの詳しい説明はこのマニュアルの対象外ですが、RESTful APIの特性を次に示します。
-
データは一連のリソースとしてモデル化されます。リソースはURIで識別されます。
-
リソースの操作には、小さく統一的な操作セットが使用されます(たとえば、PUT、POST、GET、DELETE)。
-
リソースは、複数の形式で表示できます(たとえば、ブログはHTML形式およびRSS形式で表示できます)。
-
サービスはステートレスですが、クライアントが関連リソースへのアクセスを望む可能性があるため、戻される表現の中で(通常はハイパーテキスト・リンクを提供することで)関連リソースを示します。
Oracle Application Expressのリリース4.2では、Oracle REST Data Servicesの機能を活用し、RESTful Webサービスを定義およびテストするための使いやすいグラフィカル・ユーザー・インタフェースが開発者に提供されています。
4.2 RESTfulサービスのスタート・ガイド
この項では、RESTfulサービスを紹介し、RESTfulサービスを使用するアプリケーションを開発するためのガイドラインと例を提供します。
トピック:
4.2.1 RESTfulサービスの用語
この項では、このドキュメント全体で使用されている共通の用語をいくつか紹介します。
-
RESTfulサービス: RESTfulアーキテクチャ・スタイルの原則に準拠したHTTP Webサービス。
-
リソース・モジュール: 関連するリソース・テンプレートをグループ化するために使用される構成単位。
-
リソース・テンプレート: 一部のURI (Universal Resource Identifiers)のセットにサービス要求を行える個別のRESTfulサービス。URIのセットは、リソース・テンプレートのURIパターンで定義されます
-
URIパターン: リソース・テンプレートのパターン。ルート・パターンの使用をお薦めしますが、ルート・パターンまたはURIテンプレートのいずれにもできます。
-
ルート・パターン: URIのパス部分をコンポーネント・パーツに分解することに重点をおくパターン。たとえば、
/:object/:id?
のパターンは/emp/101
と一致し(101
のid
でemp
リソースにあるアイテムのリクエストと一致)、/emp/
とも一致します(:id
パラメータには?
修飾子の注釈が付き、これはid
パラメータがオプションであることを示すため、emp
リソースのリクエストとも一致します)。ルート・パターンの詳細な説明は、
<sqldeveloper-install>\ords
およびOracle REST Data Servicesを手動でインストールした場所(存在する場合)の下にあるdocs\javadoc\plugin-api\route-patterns.html
を参照してください。 -
URIテンプレート: 所定のリソース・テンプレートが処理可能な特定のURIパターンを定義する簡易文法。たとえば、
employees/{id}
というパターンは、パスがemployees/
で始まる任意のURI (employees/2560
など)に一致します。 -
リソース・ハンドラ: 特定のリソース・テンプレートで特定のHTTPメソッドのサービスを行うために必要なロジックを提供します。たとえは、前のリソース・テンプレートでGET HTTPメソッドを行うためのロジックは次のようになります。
select empno, ename, dept from emp where empno = :id
-
HTTP操作: HTTP (HyperText Transport Protocol)により、
GET
(リソース内容の取得)、POST
(新規リソースの格納)、PUT
(既存のリソースの更新)およびDELETE
(リソースの削除)という、リソースで実行可能な標準メソッドが定義されます。
関連トピック
4.2.2 リクエスト・パスの構文要件について
Oracle REST Data Servicesは、パス・ベースの攻撃を防ぐために、各リクエストURLのパス要素の構文に対していくつかの検証チェックを実行します。
各パスは、次のルールに準拠する必要があります。
-
空や空白文字のみでない
-
次のいずれの文字も含まない: ?、#、;、%
-
null文字(\u0000)を含まない
-
次の範囲の文字を含まない: \u0001-\u0031
-
ホワイトスペースまたはピリオド(.)で終わらない
-
二重のフォワード・スラッシュ(//)または二重のバックスラッシュ(\\)を含まない
-
連続する2つ以上のピリオドを含まない(..、...など)
-
全長が{@value #MAX_PATH_LENGTH}文字以下である
-
ファイル拡張子を含んで、または含まないで、次のいずれの名前にも一致しない(大文字と小文字は区別されない): CON、PRN、AUX、CLOCK$、NUL、COM0、COM1、COM2、COM3、COM4、COM5、COM6、COM7、COM8、COM9、LPT0、LPT1、LPT2、LPT3、LPT4、LPT5、LPT6、LPT7、LPT8、LPT9
オブジェクトを自動REST有効化する場合、これらの要件を満たさないオブジェクト名は避けてください。たとえば、#EMPSという名前の表は作成しないでください。不適格な名前を持つオブジェクトを自動REST有効化するには、要件を満たす別名を使用する必要があります。
これらの要件は、URLデコードされた形式のURLに適用され、パーセント・エンコーディングによる回避の試みを阻止します。
4.2.3 インストールに含まれるドキュメント「スタート・ガイド」
Oracle REST Data Servicesをインストールすると、参考になるサブフォルダやファイルの入った例のフォルダが作成されます。インストール・フォルダの階層には、次のものがあります。
ords conf docs examples soda getting-started ...
階層の内容:
-
examples\soda
: 『Oracle REST Data Services SODA for REST開発者ガイド』の中のいくつかの例で使用されるサンプルのJSONドキュメントが含まれています。 -
examples\getting-started
:index.html
をダブルクリックすると、Oracle REST Data Servicesを使用したRESTfulサービスの開発を開始する方法についての簡潔なドキュメントが表示されます。このマニュアルでは、まず初めにSQL Developerの使用を中心に説明します。(SQL Developerは、Oracle REST Data Servicesを管理するための主ツールです。たとえば、スキーマおよび表のRESTサポートを自動的に有効にする機能は、SQL Developerでのみ使用可能です。)
4.2.4 cURLおよびRESTfulサービスのテストについて
他の項で、Webブラウザを使用したRESTfulサービスのテストについて説明しています。しかし、RESTfulサービスをテストするもう1つの便利な方法に、cURLという名前のコマンドライン・ツールを使用する方法があります。
この強力なツールはほとんどのプラットフォームで利用可能で、RESTfulサービスとの間で送受信されるデータを確認および制御できます。
curl -i https://server:port/ords/workspace/hr/employees/7369
この例では、次のようなレスポンスが生成されます。
HTTP/1.1 200 OK Server: Oracle-REST-Data-Services/2.0.6.78.05.25 ETag: "..." Content-Type: application/json Transfer-Encoding: chunked Date: Thu, 28 Mar 2014 16:49:34 GMT { "empno":7369, "ename":"SMITH", "job":"CLERK", "mgr":7902, "hiredate":"1980-12-17T08:00:00Z", "sal":800, "deptno":20 }
-i
オプションは、cURLに対し、サーバーから戻されたHTTPヘッダーを表示するように指示します。
4.2.5 RESTアクセスのためのスキーマ・オブジェクトの自動的な有効化(AutoREST)
Oracle REST Data Servicesがデータベース接続に関連付けられたシステムにインストールされている場合、AutoREST機能を使用して、そのデータベース接続と関連付けられたスキーマ内の指定された表およびビューへのOracle REST Data Servicesアクセスを簡単に有効または無効にすることができます。表、ビューまたはPL/SQLファンクション、プロシージャまたはパッケージへのRESTアクセスを有効化すると、RESTfulサービスを介したアクセスが可能になります。
AutoRESTは、データベース表をRESTリソースとして公開する素早く簡単な方法です。労力を削減するために、柔軟性とカスタマイズの容易性を若干犠牲にします。AutoRestによってデータを素早く公開できますが、(例えた言い方をすると)ガイド・レールのセットに乗せてしまいます。たとえば、出力形式や入力形式をカスタマイズできず、追加の検証も実行できません。
一方、手動で作成したリソース・モジュールでは、RESTリソースをサポートするためにSQLおよびPL/SQLを指定する必要があります。リソース・モジュールを使用することは労力を要しますが、柔軟性を向上します。たとえば、どのフィールドを含めるかのカスタマイズ、複数の表の結合、およびPL/SQLを使用した受信データの検証を実現できます。
そのため、アプリケーション開発者は、AutoRESTの「ガイド・レール」を使用するか、まさに必要なことを実行するためにリソース・モジュールを作成するかを選択する必要があります。AutoRESTを選択した場合、スキーマ内で表(または表のセット)を有効にするだけです。
スキーマを有効化することは、スキーマ内のすべての表とビューを有効化することとは異なることに注意してください。Oracle REST Data Servicesにスキーマが存在することを認識させ、HTTPに公開するリソースがゼロまたはそれ以上ある可能性があることを意味するのみです。それらのリソースは、AutoRESTリソースでも、リソース・モジュール・リソースでもかまいません。
Oracle SQL Developerの便利なウィザードを使用して、Oracle REST Data Servicesの問合せによる個々のデータベース・スキーマ・オブジェクト(表、ビュー、およびPL/SQL)へのアクセスを自動的に有効にできます。(これらの機能は、Oracle REST Data Services対応のスキーマでのみ有効で、Oracle Application Expressワークスペースでは有効でないことに注意してください。)
1つ以上の指定した表またはビューに対するOracle REST Data Servicesアクセスを有効にするには、SQL Developerで次を実行する必要があります。
-
RESTアクセス用にスキーマ(接続に関連付けられているスキーマ)を有効にします。
スキーマ・レベル: 接続に関連付けられているスキーマの(次のステップで指定する)選択したオブジェクトへのOracle REST Data Servicesアクセスを有効にするには、「接続」ナビゲータでその名前を右クリックし、「RESTサービス」、「RESTサービスの有効化」の順に選択します。
(接続に関連付けられているスキーマのオブジェクトへのOracle REST Data Servicesアクセスのサポートを削除するには、「接続」ナビゲータでその名前を右クリックし、「RESTサービス」、「RESTサービスの削除」の順に選択します。)
-
希望するオブジェクトのRESTアクセスを個別に有効化します。
表またはビュー・レベル: 指定した表またはビューへのOracle REST Data Servicesアクセスを有効化するには、「接続」ナビゲータでその名前を右クリックし、「RESTサービスの有効化」の順に選択します。
使用方法の詳細は、SQL Developerのウィザードまたはダイアログ・ボックスの「ヘルプ」ボタンをクリックします。
4.2.5.1 例: RESTfulサービスを使用してオブジェクトにアクセスする
この項では、Oracle REST Data Services問合せの使用例およびREST対応した後の表やビューに対するその他の操作の例を示します。
SQL Developerを使用して、表オブジェクトおよびビュー・オブジェクトを自動的にRESTfulサービスとして公開できます。この項では、これらのRESTfulサービスにアクセスする例を説明します。
ヒント:
こうした例は、これらのリソースにアクセスするのに使用するURLパターンを示しますが、クライアントはこれらのURLの構造の知識をハード・コーディングしないでください。かわりに、クライアントはリソースのハイパーリンクに従ってリソース間を移動してください。URLパターンの構造は、将来のリリースで進化したり、変更されたりする可能性があります。
この項では、RESTfulサービスを使用してオブジェクトにアクセスする例を説明します。
4.2.5.1.1 スキーマ・メタデータのGet
この例では、指定したスキーマの別名で、使用可能なリソースの一覧を取得します。表またはビューを自動的に有効化することで作成されるRESTfulサービスと、リソース・モジュールによって作成されるRESTfulサービスを示します。
この例では、指定したスキーマの別名で、使用可能なリソースの一覧を取得します。
パターン: GET http://<HOST>:<PORT>/ords/<SchemaAlias>/metadata-catalog/
例: GET http://localhost:8080/ords/ordstest/metadata-catalog/
結果:
{ "items": [ { "name": "EMP", "links": [ { "rel": "describes", "href": "http://localhost:8080/ords/ordstest/emp/" }, { "rel": "canonical", "href": "http://localhost:8080/ords/ordstest/metadata-catalog/emp/", "mediaType": "application/json" } ] }, { "name": "oracle.examples.hello", "links": [ { "rel": "describes", "href": "http://localhost:8080/ords/ordstest/examples/hello/" }, { "rel": "canonical", "href": "http://localhost:8080/ords/ordstest/metadata-catalog/examples/hello/", "mediaType": "application/json" } ] } ], "hasMore": false, "limit": 25, "offset": 0, "count": 2, "links": [ { "rel": "self", "href": "http://localhost:8080/ords/ordstest/metadata-catalog/" }, { "rel": "first", "href": "http://localhost:8080/ords/ordstest/metadata-catalog/" } ] }
リソースの一覧には、次が含まれます。
-
REST対応の表またはビューを示すリソース。
-
リソース・モジュールによって定義されているリソース。具体的なパス(つまり、パラメータを含まない)のリソースのみが表示されることに注意してください。たとえば、
/module/some/path/
のパスのリソースは表示されますが、/module/some/:parameter/
のパスのリソースは表示されません。
有効な各リソースには、次の2つのハイパーリンクがあります。
-
関係に
describes
のあるリンクは実際のリソースを指します。 -
関係に
canonical
のあるリンクはリソースを説明します。
4.2.5.1.2 オブジェクト・メタデータのGet
この例では、個別オブジェクトのメタデータ(オブジェクトを説明するメタデータ)を取得しています。メタデータの場所はcanonical
リンクの関係で指定されています。
パターン: GET http://<HOST>:<PORT>/ords/<SchemaAlias>/metadata-catalog/<ObjectAlias>/
例: GET http://localhost:8080/ords/ordstest/metadata-catalog/emp/
結果:
{ "name": "EMP", "primarykey": [ "empno" ], "members": [ { "name": "empno", "type": "NUMBER" }, { "name": "ename", "type": "VARCHAR2" }, { "name": "job", "type": "VARCHAR2" }, { "name": "mgr", "type": "NUMBER" }, { "name": "hiredate", "type": "DATE" }, { "name": "sal", "type": "NUMBER" }, { "name": "comm", "type": "NUMBER" }, { "name": "deptno", "type": "NUMBER" } ], "links": [ { "rel": "collection", "href": "http://localhost:8080/ords/ordstest/metadata-catalog/", "mediaType": "application/json" }, { "rel": "canonical", "href": "http://localhost:8080/ords/ordstest/metadata-catalog/emp/" }, { "rel": "describes", "href": "http://localhost:8080/ords/ordstest/emp/" } ] }
4.2.5.1.3 オブジェクト・データのGet
この例では、オブジェクトのデータを取得します。オブジェクトの各行は、JSON配列に埋め込まれているJSONオブジェクトに対応します
パターン: GET http://<HOST>:<PORT>/ords/<SchemaAlias>/<ObjectAlias>/
例: GET http://localhost:8080/ords/ordstest/emp/
結果:
{ "items": [ { "empno": 7499, "ename": "ALLEN", "job": "SALESMAN", "mgr": 7698, "hiredate": "1981-02-20T00:00:00Z", "sal": 1600, "comm": 300, "deptno": 30, "links": [ { "rel": "self", "href": "http://localhost:8080/ords/ordstest/emp/7499" } ] }, ... { "empno": 7934, "ename": "MILLER", "job": "CLERK", "mgr": 7782, "hiredate": "1982-01-23T00:00:00Z", "sal": 1300, "comm": null, "deptno": 10, "links": [ { "rel": "self", "href": "http://localhost:8080/ords/ordstest/emp/7934" } ] } ], "hasMore": false, "limit": 25, "offset": 0, "count": 13, "links": [ { "rel": "self", "href": "http://localhost:8080/ords/ordstest/emp/" }, { "rel": "edit", "href": "http://localhost:8080/ords/ordstest/emp/" }, { "rel": "describedby", "href": "http://localhost:8080/ords/ordstest/metadata-catalog/emp/" }, { "rel": "first", "href": "http://localhost:8080/ords/ordstest/emp/" } ] }
4.2.5.1.4 ページ区切りを使用した表データのGet
この例では、結果データのページ区切りを制御するパラメータのoffset
およびlimit
を指定します。
パターン: GET http://<HOST>:<PORT>/ords/<SchemaAlias>/<ObjectAlias>/?offset=<Offset>&limit=<Limit>
例: GET http://localhost:8080/ords/ordstest/emp/?offset=10&limit=5
結果:
{ "items": [ { "empno": 7900, "ename": "JAMES", "job": "CLERK", "mgr": 7698, "hiredate": "1981-12-03T00:00:00Z", "sal": 950, "comm": null, "deptno": 30, "links": [ { "rel": "self", "href": "http://localhost:8080/ords/ordstest/emp/7900" } ] }, ... { "empno": 7934, "ename": "MILLER", "job": "CLERK", "mgr": 7782, "hiredate": "1982-01-23T00:00:00Z", "sal": 1300, "comm": null, "deptno": 10, "links": [ { "rel": "self", "href": "http://localhost:8080/ords/ordstest/emp/7934" } ] } ], "hasMore": false, "limit": 5, "offset": 10, "count": 3, "links": [ { "rel": "self", "href": "http://localhost:8080/ords/ordstest/emp/" }, { "rel": "edit", "href": "http://localhost:8080/ords/ordstest/emp/" }, { "rel": "describedby", "href": "http://localhost:8080/ords/ordstest/metadata-catalog/emp/" }, { "rel": "first", "href": "http://localhost:8080/ords/ordstest/emp/?limit=5" }, { "rel": "prev", "href": "http://localhost:8080/ords/ordstest/emp/?offset=5&limit=5" } ] }
4.2.5.1.5 問合せを使用した表データのGet
この例では、戻されるオブジェクトを制限するフィルタ句を指定します。
パターン: GET http://<HOST>:<PORT>/ords/<SchemaAlias>/<ObjectAlias>/?q=<FilterClause>
例: GET http://localhost:8080/ords/ordstest/emp/?q={"deptno":{"$lte":20}}
結果:
{ "items": [ { "empno": 7566, "ename": "JONES", "job": "MANAGER", "mgr": 7839, "hiredate": "1981-04-01T23:00:00Z", "sal": 2975, "comm": null, "deptno": 20, "links": [ { "rel": "self", "href": "http://localhost:8080/ords/ordstest/emp/7566" } ] }, ... { "empno": 7934, "ename": "MILLER", "job": "CLERK", "mgr": 7782, "hiredate": "1982-01-23T00:00:00Z", "sal": 1300, "comm": null, "deptno": 10, "links": [ { "rel": "self", "href": "http://localhost:8080/ords/ordstest/emp/7934" } ] } ], "hasMore": false, "limit": 25, "offset": 0, "count": 7, "links": [ { "rel": "self", "href": "http://localhost:8080/ords/ordstest/emp/?q=%7B%22deptno%22:%7B%22%24lte%22:20%7D%7D" }, { "rel": "edit", "href": "http://localhost:8080/ords/ordstest/emp/?q=%7B%22deptno%22:%7B%22%24lte%22:20%7D%7D" }, { "rel": "describedby", "href": "http://localhost:8080/ords/ordstest/metadata-catalog/emp/" }, { "rel": "first", "href": "http://localhost:8080/ords/ordstest/emp/?q=%7B%22deptno%22:%7B%22%24lte%22:20%7D%7D" } ] }
4.2.5.1.6 主キーを使用した表の行のGet
この例では、オブジェクトを識別するキーの値を指定することでオブジェクトを取得します。
パターン: GET http://<HOST>:<PORT>/ords/<SchemaAlias>/<ObjectAlias>/<KeyValues>
ここで、<KeyValues>
はカンマで区切ったキー値のリストです(キー順)。
例: GET http://localhost:8080/ords/ordstest/emp/7839
結果:
{ "empno": 7839, "ename": "KING", "job": "PRESIDENT", "mgr": null, "hiredate": "1981-11-17T00:00:00Z", "sal": 5000, "comm": null, "deptno": 10, "links": [ { "rel": "self", "href": "http://localhost:8080/ords/ordstest/emp/7839" }, { "rel": "edit", "href": "http://localhost:8080/ords/ordstest/emp/7839" }, { "rel": "describedby", "href": "http://localhost:8080/ords/ordstest/metadata-catalog/emp/item" }, { "rel": "collection", "href": "http://localhost:8080/ords/ordstest/emp/" } ] }
4.2.5.1.7 表の行の挿入
この例では、オブジェクトにデータを挿入します。リクエストに付加するボディのデータは、挿入するデータを格納したJSONオブジェクトです。
オブジェクトに主キーがある場合、オブジェクトには主キー・フィールドに移入する挿入トリガーが必要です。表に主キーがない場合には、行のROWIDがアイテムの識別子として使用されます。
オブジェクトに主キー値を割り当てるトリガーがない場合、次の項「表の行の更新/挿入」で説明されているPUT操作をかわりに使用してください。
パターン: POST http://<HOST>:<PORT>/ords/<SchemaAlias>/<ObjectAlias>/
例:
curl -i -H "Content-Type: application/json" -X POST -d "{ \"empno\" :7, \"ename\": \"JBOND\", \"job\":\"SPY\", \"deptno\" :11 }" "http://localhost:8080/ords/ordstest/emp/ Content-Type: application/json { "empno" :7, "ename": "JBOND", "job":"SPY", "deptno" :11 }
結果:
{ "empno": 7, "ename": "JBOND", "job": "SPY", "mgr": null, "hiredate": null, "sal": null, "comm": null, "deptno": 11, "links": [ { "rel": "self", "href": "http://localhost:8080/ords/ordstest/emp/7" }, { "rel": "edit", "href": "http://localhost:8080/ords/ordstest/emp/7" }, { "rel": "describedby", "href": "http://localhost:8080/ords/ordstest/metadata-catalog/emp/item" }, { "rel": "collection", "href": "http://localhost:8080/ords/ordstest/emp/" } ] }
4.2.5.1.8 表の行の更新/挿入
この例では、オブジェクト内のデータを挿入または更新します(「アップサート」とも呼ばます)。リクエストに付加するボディのデータは、挿入または更新するデータを格納したJSONオブジェクトです。
パターン: PUT http://<HOST>:<PORT>/ords/<SchemaAlias>/<ObjectAlias>/<KeyValues>
例:
curl -i -H "Content-Type: application/json" -X PUT -d "{ \"empno\" :7, \"ename\": \"JBOND\", \"job\":\"SPY\", \"deptno\" :11 }" "http://localhost:8080/ords/ordstest/emp/7 Content-Type: application/json { "empno" :7, "ename": "JBOND", "job":"SPY", "deptno" :11 }
結果:
{ "empno": 7, "ename": "JBOND", "job": "SPY", "mgr": null, "hiredate": null, "sal": null, "comm": null, "deptno": 11, "links": [ { "rel": "self", "href": "http://localhost:8080/ords/ordstest/emp/7" }, { "rel": "edit", "href": "http://localhost:8080/ords/ordstest/emp/7" }, { "rel": "describedby", "href": "http://localhost:8080/ords/ordstest/metadata-catalog/emp/item" }, { "rel": "collection", "href": "http://localhost:8080/ords/ordstest/emp/" } ] }
4.2.5.1.9 フィルタを使用したDelete
この例では、フィルタ句で指定されたオブジェクトのデータを削除します。
パターン: DELETE http://<HOST>:<PORT>/ords/<SchemaAlias>/<ObjectAlias>/?q=<FilterClause>
例: curl -i -X DELETE http://localhost:8080/ords/ordstest/emp/?q={"deptno":11}"
結果:
{ "itemsDeleted": 1 }
4.2.5.1.10 バッチ・ロードによるPost
この例では、バッチ・ロード機能を使用してオブジェクトのデータを挿入します。リクエストに付加するボディのデータはCSVファイルです。バッチ操作の動作はオプションの問合せパラメータを使用して制御できます。このパラメータは表4-1で説明しています。
パターン: POST http://<HOST>:<PORT>/ords/<SchemaAlias>/<ObjectAlias>/batchload?<Parameters>
パラメータ:
表4-1 バッチ・ロードのパラメータ
パラメータ | 説明 |
---|---|
batchesPerCommit |
コミットの頻度を設定します。バッチがデータベースに送信された後、オプションのコミット・ポイントを設定できます。デフォルトは10個のバッチごとです。0はロードの終了までコミットを延期することを示します。型: Integer。 |
batchRows |
データベースに送信する各バッチ内の行数を設定します。デフォルトは、バッチ当たり50行です。型: Integer。 |
dateFormat |
日付データ型の書式マスクを設定します。入力データを日付型の列に変換するときに、この形式が使用されます。型: String。 |
delimiter |
ファイル内のフィールドのフィールド区切り文字を設定します。デフォルトはカンマ(,)です。 |
enclosures |
embeddedRightDouble |
errors |
エラー数の制限に使用されるユーザー・オプションを設定します。エラーの数が エラーを許容しない場合は、0を指定します。すべてのエラーを許容する(errorsMaxの値まで)場合は、UNLIMITED(-1)を指定します。 |
errorsMax |
ユーザーによって許容されるエラーの数を制限するために使用されるサービスのオプションです。これは、サービス・プロバイダ用のオプションとして用意されており、ユーザーのオプションとしては公開しません。エラーの数が エラーを許容しない場合は、0を指定します。すべてのエラーを許容する場合は、UNLIMITED(-1)を指定します。 |
lineEnd |
行の終わり(ターミネータ)を設定します。ファイルに、標準的な行の終了文字(\r、\r\nまたは\n)が含まれている場合は、 |
lineMax |
データ・ストリーム中の行(row)当たりの行(line)数を識別するための最大の行(line)の長さを設定します。 |
locale |
ロケールを設定します。 |
responseEncoding |
レスポンス・ストリームのエンコーディングを設定します。 |
responseFormat |
レスポンス・ストリームの形式を設定します。この形式は、メッセージや不良データを書式化する方法を決定します。有効な値: |
timestampFormat |
タイム・スタンプ・データ型の書式マスクを設定します。入力データをタイム・スタンプ型の列に変換するときに、この形式が使用されます。 |
timestampTZFormat |
タイム・スタンプのタイムゾーン・データ型の書式マスクを設定します。入力データをタイム・スタンプのタイムゾーン型の列に変換するときに、この形式が使用されます。 |
truncate |
ロードする前に表のデータ行を削除するか、または削除する方法、あるいはその両方を示します。 |
例:
POST http://localhost:8080/ords/ordstest/emp/batchload?batchRows=25 Content-Type: text/csv empno,ename,job,mgr,hiredate,sal,comm,deptno 0,M,SPY MAST,,2005-05-01 11:00:01,4000,,11 7,J.BOND,SPY,0,2005-05-01 11:00:01,2000,,11 9,R.Cooper,SOFTWARE,0,2005-05-01 11:00:01,10000,,11 26,Max,DENTIST,0,2005-05-01 11:00:01,5000,,11
結果:
#INFO Number of rows processed: 4 #INFO Number of rows in error: 0 #INFO Elapsed time: 00:00:03.939 - (3,939 ms) 0 - SUCCESS: Load processed without errors
4.2.5.2 問合せでのフィルタリング
この項では、REST対応の表やビューに対する問合せでのフィルタリングの例を示し、説明します。
フィルタリングは、全コレクションで見つかった項目のサブセットが含まれている複数ページのリソース全体に対し、リクエストごとの動的フィルタ定義を使用してコレクション・リソースを制限する処理です。フィルタリングは、大規模なコレクションの効率的な走査を可能にします。
問合せでフィルタリングするには、q=
FilterObjectパラメータを含め、FilterObjectはリソースに適用するカスタムな選択やソートを表すJSONオブジェクトです。たとえば、次のようなリソースを仮定します。
https://example.com/ords/scott/emp/
次の問合せには、ENAME列を「JOHN」に制限するフィルタが含まれています。
https://example.com/ords/scott/emp/?q={"ENAME":"JOHN"}
4.2.5.2.1 FilterObjectの文法
FilterObject
は、次の構文に準拠したJSONオブジェクトである必要があります。
FilterObject { orderby , asof, wmembers }
orderby
、asof
およびwmembers
属性はオプションで、その定義は次のとおりです。
orderby "$orderby": {orderByMembers} orderByMembers orderByProperty orderByProperty , orderByMembers orderByProperty columnName : sortingValue sortingValue "ASC" "DESC" "-1" "1" -1 1 asof "$asof": date "$asof": "datechars" "$asof": scn "$asof": +int wmembers wpair wpair , wmembers wpair columnProperty complexOperatorProperty columnProperty columnName : string columnName : number columnName : date columnName : simpleOperatorObject columnName : complexOperatorObject columnName : [complexValues] columnName "\p{Alpha}[[\p{Alpha}]]([[\p{Alnum}]#$_])*$" complexOperatorProperty complexKey : [complexValues] complexKey : simpleOperatorObject complexKey "$and" "$or" complexValues complexValue , complexValues complexValue simpleOperatorObject complexOperatorObject columnObject columnObject {columnProperty} simpleOperatorObject {simpleOperatorProperty} complexOperatorObject {complexOperatorProperty} simpleOperatorProperty "$eq" : string | number | date "$ne" : string | number | date "$lt" : number | date "$lte" : number | date "$gt" : number | date "$gte" : number | date "$instr" : string "$ninstr" : string "$like" : string "$null" : null "$notnull" : null "$between" : betweenValue betweenValue [null , betweenNotNull] [betweenNotNull , null] [betweenRegular , betweenRegular] betweenNotNull number date betweenRegular string number date
データ型の定義には次のものがあります。
string JSONString number JSONNumber date {"$date":"datechars"} scn {"$scn": +int}
説明:
datechars is an RFC3339 date format in UTC (Z) JSONString "" " chars " chars char char chars char any-Unicode-character except-"-or-\-or-control-character \" \\ \/ \b \f \n \r \t \u four-hex-digits JSONNumber int int frac int exp int frac exp int digit digit1-9 digits - digit - digit1-9 digits frac . digits exp e digits digits digit digit digits e e e+ e- E E+ E-
FilterObject
はRFC3986の第2.1項に従って符号化する必要があります。
4.2.5.2.2 例: FilterObjectの記述
FilterObject
の記述における演算子の例を次に示します。
ORDER BY property ($orderby) Order by with literals { "$orderby": {"SALARY": "ASC","ENAME":"DESC"} } Order by with numbers { "$orderby": {"SALARY": -1,"ENAME": 1} } ASOF property ($asof) With SCN (Implicit) { "$asof": 1273919 } With SCN (Explicit) { "$asof": {"$scn": "1273919"} } With Date (Implicit) { "$asof": "2014-06-30T00:00:00Z" } With Date (Explicit) { "$asof": {"$date": "2014-06-30T00:00:00Z"} } EQUALS operator ($eq) (Implicit and explicit equality supported._ Implicit (Support String and Dates too) { "SALARY": 1000 } Explicit { "SALARY": {"$eq": 1000} } Strings { "ENAME": {"$eq":"SMITH"} } Dates { "HIREDATE": {"$date": "1981-11-17T08:00:00Z"} } NOT EQUALS operator ($ne) Number { "SALARY": {"$ne": 1000} } String { "ENAME": {"$ne":"SMITH"} } Dates { "HIREDATE": {"$ne": {"$date":"1981-11-17T08:00:00Z"}} } LESS THAN operator ($lt) (Supports dates and numbers only) Numbers { "SALARY": {"$lt": 10000} } Dates { "SALARY": {"$lt": {"$date":"1999-12-17T08:00:00Z"}} } LESS THAN OR EQUALS operator ($lte) (Supports dates and numbers only) Numbers { "SALARY": {"$lte": 10000} } Dates { "HIREDATE": {"$lte": {"$date":"1999-12-17T08:00:00Z"}} } GREATER THAN operator ($gt) (Supports dates and numbers only) Numbers { "SALARY": {"$gt": 10000} } Dates { "SALARY": {"$gt": {"$date":"1999-12-17T08:00:00Z"}} } GREATER THAN OR EQUALS operator ($gte) (Supports dates and numbers only) Numbers { "SALARY": {"$gte": 10000} } Dates { "HIREDATE": {"$gte": {"$date":"1999-12-17T08:00:00Z"}} } In string operator ($instr) (Supports strings only) { "ENAME": {"$instr":"MC"} } Not in string operator ($ninstr) (Supports strings only) { "ENAME": {"$ninstr":"MC"} } #### LIKE operator ($like) (Supports strings. Eescape character not supported to try to match expressions with _ or % characters.) { "ENAME": {"$like":"AX%"} } #### BETWEEN operator ($between) (Supports string, dates, and numbers) Numbers { "SALARY": {"$between": [1000,2000]} } Dates { "SALARY": {"$between": [{"$date":"1989-12-17T08:00:00Z"},{"$date":"1999-12-17T08:00:00Z"}]} } Strings { "ENAME": {"$between": ["A","C"]} } Null Ranges ($lte equivalent) (Supported by numbers and dates only) { "SALARY": {"$between": [null,2000]} } Null Ranges ($gte equivalent) (Supported by numbers and dates only) { "SALARY": {"$between": [1000,null]} } #### NULL operator ($null) { "ENAME": {"$null": null} } #### NOT NULL operator ($notnull) { "ENAME": {"$notnull": null} } #### AND operator ($and) (Supports all operators, including $and and $or) Column context delegation (Operators inside $and will use the closest context defined in the JSON tree.) { "SALARY": {"$and": [{"$gt": 1000},{"$lt":4000}]} } Column context override (Example: salary greater than 1000 and name like S%) { "SALARY": {"$and": [{"$gt": 1000},{"ENAME": {"$like":"S%"}} ] } } Implicit and in columns ``` { "SALARY": [{"$gt": 1000},{"$lt":4000}] } ``` High order AND (All first columns and or high order operators -- $and and $ors -- defined at the first level of the JSON will be joined and an implicit AND) (Example: Salary greater than 1000 and name starts with S or T) { "SALARY": {"$gt": 1000}, "ENAME": {"$or": [{"$like":"S%"}, {"$like":"T%"}]} } Invalid expression (operators $lt and $gt lack column context) { "$and": [{"$lt": 5000},{"$gt": 1000}] } Valid alternatives for the previous invalid expression { "$and": [{"SALARY": {"$lt": 5000}}, {"SALARY": {"$gt": 1000}}] } { "SALARY": [{"$lt": 5000},{"$gt": 1000}] } { "SALARY": {"$and": [{"$lt": 5000},{"$gt": 1000}]} } OR operator ($or) (Supports all operators including $and and $or) Column context delegation (Operators inside $or will use the closest context defined in the JSON tree) { "ENAME": {"$or": [{"$eq":"SMITH"},{"$eq":"KING"}]} } Column context override (Example: name starts with S or salary greater than 1000) { "SALARY": {"$or": [{"$gt": 1000},{"ENAME": {"$like":"S%"}} ] } }
4.2.5.3 自動PL/SQL
この項では、HTTP(S)を介してPL/SQLをリモート・プロシージャ・コール(RPC)のために利用可能にする方法について説明します。
自動PL/SQL機能は、ステートレスなWebサービス環境でエンコーディングとデータ転送の整合性を提供するために標準を使用します。この機能を使用すると、ビューおよび表の有効化方法と同じように、Oracle REST Data Servicesを通じてパッケージ・レベルでOracle DatabaseストアドPL/SQLファンクションおよびプロシージャを有効化できます。
PL/SQLサブプログラムの自動有効化
-
PL/SQLプロシージャ
-
PL/SQLファンクション
-
PL/SQLパッケージ
PL/SQLパッケージ内のファンクションおよびプロシージャはPL/SQLパッケージ・オブジェクトの範囲内で名前を付けられているオブジェクトなので、個々に有効化することはできません。このため、粒度レベルがパッケージ・レベルでオブジェクトを有効化します。この粒度レベルは、そのパブリック・ファンクションおよびプロシージャをすべて公開可能にします。
注意:
オーバーロードしたパッケージ・ファンクションとプロシージャはサポートされていません。4.2.5.3.1 PL/SQLオブジェクトの自動有効化がサポートされているメソッドとコンテンツ・タイプ
この項では、この機能によってサポートされるメソッドおよびコンテンツ・タイプについて説明します。
注意:
この機能はRPCスタイルのインタラクションを行うため、CRUDからHTTPメソッドへの標準データ・マッピングには適用できません。サポートされるコンテンツ・タイプは、application/json
です。
4.2.5.3.2 PL/SQLオブジェクトの自動有効化
この項では、Oracle REST Data Servicesを介してPL/SQLオブジェクトを自動的に有効化する方法を説明します。
4.2.5.3.2.1 PL/SQL APIを使用した自動有効化
Oracle REST Data Services PL/SQL APIを使用してPL/SQLオブジェクトを有効化できます。
PL/SQLパッケージを有効化するには、次のサンプル・コード・スニペットに示すように、Oracle REST Data Services PL/SQL APIを使用します。
BEGIN
ords.enable_object(
p_enabled => TRUE,
p_schema => 'MY_SCHEMA',
p_object => 'MY_PKG',
p_object_type => 'PACKAGE',
p_object_alias => 'my_pkg',
p_auto_rest_auth => FALSE);
commit;
END;
/
例4-1 PL/SQLファンクションの有効化
PL/SQLファンクションを有効化するには、次のサンプル・コード・スニペットに示すように、Oracle REST Data Services PL/SQL APIを使用します。
BEGIN
ords.enable_object(
p_enabled => TRUE,
p_schema => 'MY_SCHEMA',
p_object => 'MY_FUNC',
p_object_type => 'FUNCTION',
p_object_alias => 'my_func',
p_auto_rest_auth => FALSE);
commit;
END;
/
例4-2 PL/SQLプロシージャの有効化
PL/SQLプロシージャを有効化するには、次のサンプル・コード・スニペットに示すように、Oracle REST Data Services PL/SQL APIを使用します。
BEGIN
ords.enable_object(
p_enabled => TRUE,
p_schema => 'MY_SCHEMA',
p_object => 'MY_PROC',
p_object_type => 'PROCEDURE',
p_object_alias => 'my_proc',
p_auto_rest_auth => FALSE);
commit;
END;
/
4.2.5.3.2.2 SQL Developerを使用したPL/SQLオブジェクトの自動有効化
この項では、SQL Developer 4.2以降を使用してPL/SQLオブジェクトを有効化する方法を説明します。
SQL Developerを使用してPL/SQLオブジェクト(たとえば、パッケージ)を有効化するには、次のステップを実行します。
注意:
これでパッケージ、ファンクションおよびプロシージャを有効化できるようになりました。ただし、有効化の粒度は、パッケージ全体レベル、スタンドアロン・ファンクション・レベル、またはスタンドアロン・プロシージャ・レベルのいずれかです。-
SQL Developerで、次の図に示すようにパッケージを右クリックします。
-
「RESTfulサービスを有効にする」を選択して、次のウィザード・ページを表示します。
-
オブジェクトの有効化: このオプションを有効にします(つまり、パッケージのRESTアクセスを有効にします)。
-
オブジェクト別名: オブジェクト別名として
registry_pkg
を受け入れます。 -
承認が必要: 簡潔性を保つため、このオプションは無効にしておきます。
-
ウィザードのRESTfulサマリー・ページで「終了」をクリックします。
-
4.2.5.3.3 PL/SQLエンドポイントの生成
HTTPエンドポイントは、有効なデータベース・オブジェクトに対してリクエストに応じて動的に生成されます。Oracle REST Data Servicesは、問合せを使用してエンドポイントを生成するために、接続したデータベース・カタログを使用します。
HTTPエンドポイントを生成するため、すべてのデータベース・オブジェクトに対して次のルールが適用されます。
-
名前はすべて小文字に変換されます
-
エンドポイントがすでに割り当てられていなければ、生成されます
ストアド・プロシージャおよびストアド・ファンクションのエンドポイント
ファンクションまたはプロシージャ名は、同じネームスペースの表やビューと同じ方法でURL内に生成されます。
例4-3 ストアド・プロシージャのためのエンドポイントの生成
CREATE OR REPLACE PROCEDURE MY_SCHEMA.MY_PROC IS
BEGIN
NULL;
END;
http://localhost:8080/ords/my_schema/my_proc/
例4-4 パッケージ・プロシージャおよびファンクションのエンドポイント
パッケージ、ファンクションおよびプロシージャ・エンドポイントは、パッケージ名を親として生成されます。オーバーロードしていないか、小文字名がまだ使用されていないファンクションとプロシージャのエンドポイントが生成されます。
次のコード・スニペットで定義されているようにMY_PKGパッケージがある場合:
CREATE OR REPLACE PACKAGE MY_SCHEMA.MY_PKG AS
PROCEDURE MY_PROC;
FUNCTION MY_FUNC RETURN VARCHAR2;
PROCEDURE MY_PROC2;
PROCEDURE "my_proc2";
PROCEDURE MY_PROC3(P1 IN VARCHAR);
PROCEDURE MY_PROC3(P2 IN NUMBER);
END MY_PKG;
http://localhost:8080/ords/my_schema/my_pkg/MY_PROC
http://localhost:8080/ords/my_schema/my_pkg/MY_FUNC
注意:
プロシージャmy_proc2
のエンドポイントは、名前を小文字に変換すると一意にならないため生成されません。プロシージャmy_proc3
のエンドポイントは、オーバーロードしているため生成されません。
4.2.5.3.4 リソース入力ペイロード
入力ペイロードは、REST標準に従った値を持つJSONドキュメントです。
ペイロードは、次のコード・スニペットに示すように、INまたはIN OUTの各パラメータに対する名前/値ペアを含んでいる必要があります。
{
"p1": "abc",
"p2": 123,
"p3": null
}
注意:
INまたはIN OUTパラメータがない場合、次のコード・スニペットに示すように、空のJSONボディが必要です。{
}
4.2.6 SQLおよびPL/SQLを使用したRESTful Servicesの手動作成
この項では、SQLおよびPL/SQLを使用して手動でRESTful Servicesを作成する方法を説明し、JSONドキュメントを使用してRESTリクエストのボディにあるストアド・プロシージャにパラメータを渡す方法を表示します。
4.2.6.1 Oracle REST Data Servicesのパラメータ引き渡しメカニズムについて
-
RESTリクエスト(たとえば
POST
またはPUT
メソッド)のボディでJSONを使用できます。ここで、各パラメータはJSONの名前/値ペアです。 -
URIの必須パラメータに対して、および他の特別な事例でルート・パターンを使用して、ボディを持たないRESTリクエスト(
GET
メソッドなど)のパラメータを指定できます。 -
URIのオプションのパラメータに対して、および他の特別な事例で問合せ文字列を使用して、ボディを持たないRESTリクエスト(
GET
メソッドなど)のパラメータを指定できます。
パラメータ引き渡しタスク実行前に完了しておく必要がある前提条件セットアップ・タスク
この前提条件セットアップ情報は、「RESTfulサービスのスタート・ガイド」の項のステップ1および2を完了していることを前提にしています。そこでは、ordstest
スキーマおよびemp
データベース・テーブルをREST対応にし(ステップ1)、SQL問合せからRESTfulサービスを作成、テストしました(ステップ2)。これら2つのステップを、パラメータ引き渡しタスクを実行する前に完了する必要があります(次以降のサブセクションを参照)。
関連トピック
4.2.6.1.1 JSONを使用したパラメータの引き渡し
この項では、RESTリクエスト(たとえばPOST
またはPUT
メソッド)のボディでJSONドキュメントを使用してストアド・プロシージャにパラメータを渡す方法を示します(各パラメータは名前/値ペア)。この操作はレコード上で更新を実行し、その結果、レコードに対する変更がOUT
パラメータとして戻されます。
次のステップを実行します。
注意:
-
すべてのパラメータはオプションです。 JSONドキュメントでパラメータの名前/値ペアを省略すると、パラメータは
NULL
に設定されます。 -
名前/値ペアは、JSONドキュメント内に、任意の順序で並べることができます。 JSONを使用すると、JSONドキュメントでこの点に多くの柔軟性を得られます。
-
1レベルのJSONのみサポートされます。JSONオブジェクトまたは配列をネストすることはできません。
4.2.6.1.2 ルート・パターンを使用したパラメータの引き渡し
GET
メソッドなど)。
まず、多くのバインド変数を持つemp
表で、問合せに対してGET
メソッド・ハンドラを作成します。このステップでは、ルート・パターンを使用して、必要なパラメータ値を指定します。
ルート・パターンを使用していくつかの必要なパラメータ値を持つGET
メソッドを送信するには、次のステップを実行します。
問合せは、Ward、MartinおよびTurnerという名のセールスマンに対応する3件のレコードを戻します。
関連項目:
ルート・パターンの詳細は、Oracle REST Data Servicesディストリビューションに含まれるドキュメントdocs/javadoc/plugin-api/route-patterns.html
と、ドキュメント「Oracle REST Data Servicesのルート・パターン」を参照してください。
4.2.6.1.3 オプションのパラメータのための問合せ文字列の使用
この項では、URIでルート・パターンを使用してRESTリクエストにパラメータを指定する方法を説明します(ボディを持たないGETメソッドなど)。任意の問合せにおいて、その他のオプションのバインド変数に対して問合せ文字列を使用できます。
問合せ文字列を使用する構文は次のとおりです: ?parm1=value1&parm2=value2 … &parmN=valueN
。
たとえば、問合せhttp://localhost:8080/ords/ordstest/test/emp/SALESMAN/30
をさらにフィルタする場合、問合せ文字列を使用していくつかのパラメータ名/値ペアとともにGETメソッドを送信するには、mgr
(管理者)が7698
でsal
(給与)が1500
である従業員を、問合せ文字列?mgr=7698&sal=1500
をURLに付加することで選択します: http://localhost:8080/ords/ordstest/test/emp/SALESMAN/30?mgr=7698&sal=1500
。
エンドポイントをテストするには、WebブラウザにURL「http://localhost:8080/ords/ordstest/test/emp/SALESMAN/30?mgr=7698&sal=1500」を入力します(次の図を参照)。
図4-10 問合せ文字列を使用してGETメソッドとともにいくつかのパラメータ名/値ペアを送信した結果をブラウザを使用して表示する
「図4-10 問合せ文字列を使用してGETメソッドとともにいくつかのパラメータ名/値ペアを送信した結果をブラウザを使用して表示する」の説明
この問合せは、名前がTurner、部門が30、給与が1500、管理者が7698であるセールスマンに対応する1件のレコードを戻します。
-
パラメータ値をURLエンコードするのは有効です。必ずしも必要ではないこともありますが、行っても安全です。これにより、インターネットにより何かが改変されること、たとえば、特殊文字が障害を引き起こす可能性がある他の文字に変換されることを防げます。RESTクライアントにこの機能があることもありますし、フレーズ
urlエンコーダ
でインターネットを検索することでその機能があるツールを見つけることもできます。 -
URIでパラメータ・リストの末尾に決してバックスラッシュを入れないでください。そうしないと、
404 Not Found
エラーが表示される場合があります。
関連項目:
JSONを使用してパラメータ値を渡す経験をさらに充実させるには、ORDSチュートリアル(OBE)の演習4およびデータベース・アプリケーション開発仮想イメージを参照します。
4.2.6.2 SQL/JSONデータベース・ファンクションの使用
この項では、Oracle Database 12c リリース2 (12.2)で利用できるSQL/JSONデータベース・ファンクションを使用して、ネストされたJSONオブジェクトと階層関係表を互いにマップするために説明します。
この項には次のトピックが含まれます:
4.2.6.2.1 ネストされたJSONオブジェクトの関係表への挿入
この項では、ネスト配列を持つJSONオブジェクトを複数の階層的な関係表に挿入する方法を説明します。
この機能を実装するために使用される2つの主要なテクノロジは次のとおりです。
-
Oracle REST Data Servicesが提供してPOSTおよび他のRESTコールのボディにあるJSONおよび他のコンテンツをPL/SQL RESTハンドラに配信する
:body
バインド変数 -
Oracle Database 12cリリース2 (12.2)で提供されるJSON_TABLEおよびその他のSQL/JSON演算子
関係表にデータを挿入するためのこれらのテクノロジを使用する利点のいくつかを次に示します。
-
機能を実装するための要件が最小限です。たとえば、JSONパーサー・ソフトウェアのインストールは不要です
-
JSONからの関係マッピングが単純な場合、書くのも読むのも簡単な、単純な宣言型コードを使用できます
-
より複雑なマッピングを処理する機能は強力で洗練されています。次のものが含まれます。
-
NULLSおよびブール値をマッピングするためのメカニズム
-
JSONを処理するための洗練されたメカニズム。JSONは時間とともに進化します。このため、マッピング・コードは、JSONドキュメントの古いバージョンも新しいバージョンも処理できる必要があります。
たとえば、単純なスカラー値が進化して、複数のスカラーまたはネストされたスカラー値やオブジェクトの配列を含むJSONオブジェクトになる場合があります。スカラー値を戻すSQL/JSON演算子は、単純なスカラーがこれらのより精巧な構造内に埋め込まれた場合でも、引き続き機能できます。特別なメカニズム(Ordinality列と呼ばれます)を使用して、値が導出されたところから構造を決定することができます。
-
関連項目:
4.2.6.2.1.1 :bodyバインド変数の使用法
この項では、:body
バインド変数を使用するために役に立つヒントをいくつか提供します。
:body
バインド変数を使用する際に役に立ついくつかのヒントを次に示します。
-
:body
バインド変数は、一度のみ、アクセスまたは参照解除できます。以降のアクセスは、NULL値を戻します。このため、2つのJSON_Table操作で使用するには、その前にローカルのL_PO
変数に:body
にバインド変数を割り当てる必要があります。 -
:body
バインド変数はBLOBデータ型であり、BLOB変数にのみ割り当てることができます。注意:
L_PO
はBLOB変数なので、JSON_TABLEファンクションの式の後にFORMAT JSON
句を使用する必要があります。詳細は項を参照。:body
バインド変数は、画像データなど、他のタイプのデータとともに使用できます。
関連項目:
-
イメージ・ギャラリの作成。画像データを持つ
:body
バインド変数の使用の作業例。
4.2.6.2.1.2 ネストされたLineItemsがあるJSON発注書の例
この項では、ネストされたLineItemsがあるJSON発注書を取得し、PurchaseOrder表の行およびLineItem表の行に挿入する例を示します。
例4-5 ネストされたLineItemsがあるネストされたJSON発注書
{"PONumber" : 1608,
"Requestor" : "Alexis Bull",
"CostCenter" : "A50",
"Address" : {"street" : "200 Sporting Green",
"city" : "South San Francisco",
"state" : "CA",
"zipCode" : 99236,
"country" : "United States of America"},
"LineItems" : [ {"ItemNumber" : 1,
"Part" : {"Description" : "One Magic Christmas",
"UnitPrice" : 19.95,
"UPCCode" : 1313109289},
"Quantity" : 9.0},
{"ItemNumber" : 2,
"Part" : {"Description" : "Lethal Weapon",
"UnitPrice" : 19.95,
"UPCCode" : 8539162892},
"Quantity" : 5.0}]}'
4.2.6.2.1.3 PurchaseOrderおよびLineItems表の表定義
この項では、PurchaseOrderおよびLineItem表に定義を提供します。
PurchaseOrderおよびLineItems表の定義は次のとおりです。
CREATE TABLE PurchaseOrder (
PONo NUMBER (5),
Requestor VARCHAR2 (50),
CostCenter VARCHAR2 (5),
AddressStreet VARCHAR2 (50),
AddressCity VARCHAR2 (50),
AddressState VARCHAR2 (2),
AddressZip VARCHAR2 (10),
AddressCountry VARCHAR2 (50),
PRIMARY KEY (PONo));
CREATE TABLE LineItem (
PONo NUMBER (5),
ItemNumber NUMBER (10),
PartDescription VARCHAR2 (50),
PartUnitPrice NUMBER (10),
PartUPCCODE NUMBER (10),
Quantity NUMBER (10),
PRIMARY KEY (PONo,ItemNumber));
4.2.6.2.1.4 POSTリクエストのPL/SQLハンドラ・コード
この項では、POSTリクエストに対応するサンプルのPL/SQLハンドラ・コードを示します。ハンドラ・コードは、PurchaseOrder表の行およびLineItem表の行に発注書を挿入するために使用されます。
例4-6 POSTリクエストに対して使用されたPL/SQLハンドラ・コード
Declare
L_PO BLOB;
Begin
L_PO := :body;
INSERT INTO PurchaseOrder
SELECT * FROM json_table(L_PO FORMAT JSON, '$'
COLUMNS (
PONo Number PATH '$.PONumber',
Requestor VARCHAR2 PATH '$.Requestor',
CostCenter VARCHAR2 PATH '$.CostCenter',
AddressStreet VARCHAR2 PATH '$.Address.street',
AddressCity VARCHAR2 PATH '$.Address.city',
AddressState VARCHAR2 PATH '$.Address.state',
AddressZip VARCHAR2 PATH '$.Address.zipCode',
AddressCountry VARCHAR2 PATH '$.Address.country'));
INSERT INTO LineItem
SELECT * FROM json_table(L_PO FORMAT JSON, '$'
COLUMNS (
PONo Number PATH '$.PONumber',
NESTED PATH '$.LineItems[*]'
COLUMNS (
ItemNumber Number PATH '$.ItemNumber',
PartDescription VARCHAR2 PATH '$.Part.Description',
PartUnitPrice Number PATH '$.Part.UnitPrice',
PartUPCCode Number PATH '$.Part.UPCCode',
Quantity Number PATH '$.Quantity')));
commit;
end;
4.2.6.2.1.5 REST APIサービスの作成によるハンドラの起動
この項では、REST APIサービスを作成してハンドラを起動する方法を説明します。Oracle REST Data Servicesを使用します。
REST APIサービスをセットアップするために、RESTコールの対象となるリソースを識別するためにURIが定義されます。URIは、Oracle REST Data Servicesが特定のハンドラにREST HTTPコールをルーティングするためにも使用されます。 このURIの一般的な書式は次のとおりです。
<server>:<port>/ords/<schema>/<module>/<template>/<parameters>
ここで、<server>:<port>
は、Oracle REST Data Serviceがインストールされた場所です。テスト目的で、URIのmoduleおよびtemplateの代わりに、それぞれdemoおよびtestを使用することができます。モジュールは、REST APIの対象となるリソースを定義する関連のテンプレートをまとめてグループ化するために使用されます。
REST APIサービスを作成するには、次のいずれかの方法を使用します。
-
Oracle REST Data Services PL/SQL APIを使用して、POST挿入のためにRESTサービスとハンドラを定義します。次に、PurchaseOrderおよびLineItem表を含むデータベース・サーバー上の
jsontable
スキーマに接続します。注意:
JSON_TABLEおよび他のSQL/JSON演算子は、エスケープする必要があるため、一重引用符を使用します。たとえば、すべての一重引用符(’)を二重引用符(“)に置き換える必要があります。 -
SQL DeveloperのOracle REST Data Services、「REST開発」ペインを使用して、RESTサービスを定義します。
4.2.6.2.1.6 PL/SQL APIを使用したRESTサービスおよびハンドラの定義
この項では、Oracle REST Data Services PL/SQL APIを使用して、POST挿入のためにRESTサービスとハンドラを定義する方法を示します。
代替として、SQL DeveloperでOracle REST Data Servicesの「REST開発」ペインを使用して、モジュール、テンプレートおよびハンドラを作成できます。
BEGIN
ORDS.ENABLE_SCHEMA(
p_enabled => TRUE,
p_schema => 'ORDSTEST',
p_url_mapping_type => 'BASE_PATH',
p_url_mapping_pattern => 'ordstest',
p_auto_rest_auth => FALSE);
ORDS.DEFINE_MODULE(
p_module_name => 'demo',
p_base_path => '/demo/',
p_items_per_page => 25,
p_status => 'PUBLISHED',
p_comments => NULL);
ORDS.DEFINE_TEMPLATE(
p_module_name => 'demo',
p_pattern => 'test',
p_priority => 0,
p_etag_type => 'HASH',
p_etag_query => NULL,
p_comments => NULL);
ORDS.DEFINE_HANDLER(
p_module_name => 'demo',
p_pattern => 'test',
p_method => 'POST',
p_source_type => 'plsql/block',
p_items_per_page => 0,
p_mimes_allowed => '',
p_comments => NULL,
p_source => '
declare
L_PO BLOB := :body;
begin
INSERT INTO PurchaseOrder
SELECT * FROM json_table(L_PO FORMAT JSON, ''$''
COLUMNS (
PONo Number PATH ''$.PONumber'',
Requestor VARCHAR2 PATH ''$.Requestor'',
CostCenter VARCHAR2 PATH ''$.CostCenter'',
AddressStreet VARCHAR2 PATH ''$.Address.street'',
AddressCity VARCHAR2 PATH ''$.Address.city'',
AddressState VARCHAR2 PATH ''$.Address.state'',
AddressZip VARCHAR2 PATH ''$.Address.zipCode'',
AddressCountry VARCHAR2 PATH ''$.Address.country''));
INSERT INTO LineItem
SELECT * FROM json_table(L_PO FORMAT JSON, ''$''
COLUMNS (
PONo Number PATH ''$.PONumber'',
NESTED PATH ''$.LineItems[*]''
COLUMNS (
ItemNumber Number PATH ''$.ItemNumber'',
PartDescription VARCHAR2 PATH ''$.Part.Description'',
PartUnitPrice Number PATH ''$.Part.UnitPrice'',
PartUPCCode Number PATH ''$.Part.UPCCode'',
Quantity Number PATH ''$.Quantity'')));
commit;
end;'
);
COMMIT;
END;
4.2.6.2.2 階層リレーショナル・データからのネストされたJSONオブジェクトの生成
この項では、Oracle REST Data Servicesを使用して、階層(親/子)関係内の関係表を問い合わせ、ネストされたJSON形式でデータを戻す方法を説明します。
この機能を実装するために使用される2つの主要なテクノロジは次のとおりです。
-
Oracle Database 12c リリース2 (12.2)で利用できる新しいSQL/JSONファンクション。
json_objects
を使用して関係表からJSONオブジェクトを生成したり、json_arrayagg
を使用してネストされた(子)関係表からネストされたJSON配列を生成したりできます。 -
RESTサービス・ハンドラが次の種類のデータを戻すSQL問合せを実行できるようにするために使用されるOracle REST Data Servicesメディア・ソース・タイプ:
-
データのHTTP Content-Type (この場合はapplication/json)
-
json_object
によって戻されるJSONデータ
-
この手法を使用する利点のいくつかを次に示します。
-
機能を実装するための要件が最小限です。たとえば、JSONパーサー・ソフトウェアのインストールは不要です
-
書きやすく読みやすいシンプルな宣言型コーディングにより、JSONオブジェクトから関係表へのマッピングがシンプルになる。
-
より複雑なマッピングを処理する機能は強力で洗練されています。これには、NULLSおよびブール値をマッピングするためのメカニズムが含まれます。
たとえば、Oracle DatabaseのNULLは、JSON要素の欠如、またはJSONのNULL値に変換できます。Oracle Database はブール型を格納しませんが、SQL/JSONファンクションでは、データベース内の文字列または数値の値をブーリアンのTRUEまたはFALSEの値にマッピングできます。
4.2.6.2.2.1 階層関係表からのネストされたJSONオブジェクトの生成例
この項では、ネストされたJSON発注書の形式でPurchaseOrderおよびLineItem関係表に挿入したデータを問い合わせるか、GETする方法を説明します。
例4-7 関係表上でOracle REST Data Servicesの問合せを使用してネストされたJSONオブジェクトを生成するGETハンドラ・コード
SELECT 'application/json', json_object('PONumber' VALUE po.PONo,
'Requestor' VALUE po.Requestor,
'CostCenter' VALUE po.CostCenter,
'Address' VALUE
json_object('street' VALUE po.AddressStreet,
'city' VALUE po.AddressCity,
'state' VALUE po.AddressState,
'zipCode' VALUE po.AddressZip,
'country' VALUE po.AddressCountry),
'LineItems' VALUE (select json_arrayagg(
json_object('ItemNumber' VALUE li.ItemNumber,
'Part' VALUE
json_object('Description' VALUE li.PartDescription,
'UnitPrice' VALUE li.PartUnitPrice,
'UPCCode' VALUE li.PartUPCCODE),
'Quantity' VALUE li.Quantity))
FROM LineItem li WHERE po.PONo = li.PONo))
FROM PurchaseOrder po
WHERE po.PONo = :id
4.2.6.2.2.2 テンプレートとGETハンドラを定義するためのPL/SQL APIコール
この項では、作成したモジュールに新しいテンプレートを作成するためのOracle REST Data Services PL/SQL APIコールの例を提供します。
例4-8 demo
モジュールに新しいtest/:id
テンプレートおよびGETハンドラを作成するためのPL/SQL APIコール
Begin
ords.define_template(
p_module_name => 'demo',
p_pattern => 'test/:id');
ords.define_handler(
p_module_name => 'demo',
p_pattern => 'test/:id',
p_method => 'GET',
p_source_type => ords.source_type_media,
p_source => '
SELECT ''application/json'', json_object(''PONumber'' VALUE po.PONo,
''Requestor'' VALUE po.Requestor,
''CostCenter'' VALUE po.CostCenter,
''Address'' VALUE
json_object(''street'' VALUE po.AddressStreet,
''city'' VALUE po.AddressCity,
''state'' VALUE po.AddressState,
''zipCode'' VALUE po.AddressZip,
''country'' VALUE po.AddressCountry),
''LineItems'' VALUE (select json_arrayagg(
json_object(''ItemNumber'' VALUE li.ItemNumber,
''Part'' VALUE
json_object(''Description'' VALUE li.PartDescription,
''UnitPrice'' VALUE li.PartUnitPrice,
''UPCCode'' VALUE li.PartUPCCODE),
''Quantity'' VALUE li.Quantity))
FROM LineItem li WHERE po.PONo = li.PONo))
FROM PurchaseOrder po
WHERE po.PONo = :id '
);
Commit;
End;
4.2.6.2.3 RESTfulサービスのテスト
この項では、Oracleデータベースにアクセスして結果をJSON形式で取得するためにPOSTおよびGET RESTful Servicesをテストする方法を示します。
この項には次のトピックが含まれます:
4.2.6.2.3.1 JSONオブジェクトのデータベースへの挿入
この項では、JSON発注書のデータベースへの挿入をテストする方法を表示します。
URIパターン: http://<HOST>:<PORT>/ords/<SchemaAlias>/<module>/<template>
例:
メソッド: POST
URIパターン: http://localhost:8080/ords/ordstest/demo/test/
po1.json
のようにファイルを作成します。{"PONumber" : 1608,
"Requestor" : "Alexis Bull",
"CostCenter" : "A50",
"Address" : {"street" : "200 Sporting Green",
"city" : "South San Francisco",
"state" : "CA",
"zipCode" : 99236,
"country" : "United States of America"},
"LineItems" : [ {"ItemNumber" : 1,
"Part" : {"Description" : "One Magic Christmas",
"UnitPrice" : 19.95,
"UPCCode" : 1313109289},
"Quantity" : 9.0},
{"ItemNumber" : 2,
"Part" : {"Description" : "Lethal Weapon",
"UnitPrice" : 19.95,
"UPCCode" : 8539162892},
"Quantity" : 5.0}]}'
curl -i -H "Content-Type: application/json" -X POST -d @po1.json "http://localhost:8080/ords/ordstest/demo/test/"cURLコマンドは、次のレスポンスを戻します。
HTTP/1.1 200 OK
Transfer-Encoding: chunked
4.2.7 Oracle REST Data Servicesでの日付の使用について
Oracle REST Data Servicesを使用すると、開発者は、Oracle Database、Oracle Database 12c JSONドキュメント・ストアへのRESTインタフェースを可能なかぎり短時間で簡単に作成できます。Oracle Databaseで作業する場合、開発者は表に対してAutoREST機能を使用したり、より複雑な操作のためにSQLおよびPL/SQLルーチンを使用してカスタム・モジュールを作成したりできます。
Oracle REST Data Servicesでは、文字列内の日付をエンコーディングするためにRFC3339標準を使用します。通常、使用される日付形式はdd-mmm-yyyyです(例: 15-Jan-2017)。Oracle REST Data Servicesは、Oracle Databaseで値の挿入や更新などの操作を実行したときに、指定された形式のJSON文字列をOracle日付データ型に自動的に変換します。JSON文字列に再変換する場合、Oracle REST Data ServicesはOracle日付データ型を文字列形式に自動的に変換します。
注意:
JSONは日付データ型をサポートしませんが、Oracle Databaseは日付データ型をサポートします。この項には次のトピックが含まれます:
関連項目:
時刻やタイムゾーンの処理方法などの詳細は次のページを参照してください: jsao_io_dates
4.2.7.1 Oracle REST Data Servicesによる日時処理について
データがRESTリクエストから到着すると、Oracle REST Data ServicesがISO 8601文字列を解析し、Oracle DatabaseのTIMESTAMP
データ型に変換する場合があります。これは、AutoREST (POST
およびPUT
)でも、カスタム・モジュールのバインド変数でも発生します。TIMESTAMP
はタイムゾーン関連コンポーネントをサポートしないので、DATETIME
値はOracle REST Data Servicesが変換処理時に使用するタイムゾーンに設定されることを覚えておいてください。
RESTリクエストへのレスポンスを作成する場合、Oracle REST Data ServicesはOracle DatabaseのDATETIME
値をズールーのISO 8601文字列に変換します。これは、AutoREST (GET
)と、SQL問合せ(GET)にマッピングされるカスタム・モジュールで発生します。DATE
およびTIMESTAMP
データ型の場合、タイムゾーン関連のコンポーネントを持たないため、タイムゾーンはOracle REST Data Servicesが実行されているタイムゾーンとみなされ、ズールーへの変換はそこから行われます。
-
Oracle REST Data Servicesがデータベースのデータに従う適切なタイムゾーン(たとえば、日付をデータベースに入れたいタイムゾーン)を使用していることを確認します。
-
NLS設定(time_zone)をストリーム中で変更しないでください。
ISO 8601文字列に言及していますが、Oracle REST Data Servicesは実際には文字列をサポートしていることに注意してください。RFC3339文字列はISO 8601文字列に準拠しているサブセットです。JSON.stringify(date)
によって戻されるデフォルトの形式がサポートされます。
警告:
TIMESTAMP WITH TIME ZONE
またはTIMESTAMP WITH LOCAL TIME ZONE
への暗黙的なデータ変換に関する問題を防止するために、Oracle REST Data Servicesが使用するタイムゾーンがセッション・タイムゾーンとの同期を維持することが重要です。デフォルトでOracle REST Data Servicesは自動的にこれを行いますが、開発者はALTER SESSION
文でセッション・タイムゾーンを変更できます。
4.2.7.2 タイムゾーンの設定について
Oracle REST Data Servicesの起動時に、それにより内部で実行されるJVMは、Oracle REST Data Servicesが様々なタイムゾーン変換に使用するタイムゾーンを取得およびキャッシュします。デフォルトでは、タイムゾーンはオペレーティング・システム(OS)から取得されるため、Oracle REST Data Servicesが使用するタイムゾーンを変更する簡単な方法は、OSのタイムゾーンを変更し、続いてOracle REST Data Servicesまたはそれが実行されているアプリケーション・サーバーを再起動することです。言うまでもなく、タイムゾーンを変更するための指示は、オペレーティング・システムにより異なります。
もしなんらかの理由でOSと同じタイムゾーンを使用したくない場合、Java環境変数Duser.timezone
を使用してデフォルトをオーバーライドすることができます。その変数が正確にはどのように設定されているかは、スタンドアロン・モードとJavaアプリケーション・サーバーのどちらで実行されているかにより異なります。次のトピックではいくつか例を示します。
スタンドアロン・モード
Oracle REST Data Servicesをスタンドアロン・モードで実行する場合、-jar
オプションの前のコマンドライン・オプションとして指定することで、Java環境変数を設定できます。
例4-9 Duser.timezone Java環境変数のスタンドアロン・モードでの設定
次のコード例は、スタンドアロン・モードでコマンドラインからタイムゾーンを設定する方法を示しています。
$ java -Duser.timezone=America/New_York -jar ords.war standalone
Javaアプリケーション・サーバー — Tomcat 8
Javaアプリケーション・サーバー、Tomcat 8では、おそらくバージョンに関係なく、環境変数CATALINA_OPTS
を使用してタイムゾーンを設定できます。これに関して推奨される方法は、CATALINA_BASE/bin/catalina.sh
を直接変更しないことです。その代わりに、CATALINA_BASE/bin
にsetenv.sh
という名前のスクリプトを作成することで環境変数を設定します。
例4-10 Duser.timezone Java環境変数のJavaアプリケーション・サーバーでの設定
次のコード例は、Javaアプリケーション・サーバー — Tomcat 8でタイムゾーンを設定するための、setenv.sh
スクリプトの内容を示しています。
CATALINA_TIMEZONE="-Duser.timezone=America/New_York"
CATALINA_OPTS="$CATALINA_OPTS $CATALINA_TIMEZONE
4.2.7.3 Application ExpressでのサンプルのRESTfulサービスの調査(チュートリアル)
SQL Developerは最新のOracle REST Data Servicesリリース、つまり3.0.Xをサポートしているため、SQL Developerを使用してOracle REST Data Servicesアプリケーションを開発することをお薦めします。Application Expressには、RESTおよびOracle REST Data Servicesの基本的な概念を習得するのに便利なチュートリアルが用意されています。ただし、チュートリアルは以前のOracle REST Data Servicesリリース(2.0.X)を使用しています。チュートリアルの使用方法について説明している有用なヒントをいくつか次に示します。
Application Expressインスタンスがサンプルのアプリケーションおよびサンプルのデータベース・オブジェクトを自動的にワークスペースに追加するように構成されている場合、リソース・モジュールのリストにoracle.example.hr
という名前のサンプルのリソース・モジュールが表示されます。リソース・モジュールがリストにない場合は、RESTfulサービス・ページの右側にあるサンプル・データのリセットタスクをクリックし、サンプルのリソース・モジュールを作成できます。
4.3 RESTfulサービスへのセキュアなアクセスの構成
この項では、RESTfulサービスへのセキュアなアクセスの構成方法について説明します。
RESTful APIは、それぞれのリソースが一意のURIを持つ複数のリソースから構成されています。リソースのセットは権限によって保護できます。権限はロールのセットを定義し、認証済のユーザーのうちの少なくとも1人は、権限によって保護されたリソースへのアクセス権を持っている必要があります。
特定の権限によって保護されるリソースを構成するには、権限のマッピングを作成する必要があります。権限のマッピングは、権限が保護するリソースを特定するパターンのセットを定義します。
トピック:
4.3.1 認証
ユーザーは、ファースト・パーティのCookieベースの認証またはサード・パーティのOAuth 2.0ベースの認証を使用して認証できます。
トピック:
4.3.1.1 ファースト・パーティのCookieベースの認証
ファースト・パーティは、RESTful APIの作成者です。ファースト・パーティのアプリケーションは、RESTful APIと同じWebオリジンにデプロイされたWebアプリケーションです。ファースト・パーティのアプリケーションは、Webアプリケーションが使用しているものと同じCookieセッションを使用し、RESTful APIに自身を認証し、権限を付与することが可能です。ファースト・パーティのアプリケーションにはRESTful APIへの完全なアクセス権があります。
4.3.1.2 サード・パーティのOAuth 2.0ベースの認証
サード・パーティは、RESTful APIの作成者以外のパーティです。サード・パーティのアプリケーションは、ファースト・パーティのアプリケーションと同じようには信頼できません。そのため、サード・パーティ製のアプリケーションに対し、選択的に制限付きのRESTful APIへのアクセス権を付与するための仲介手段が必要となります。
OAuth 2.0プロトコルは、RESTful APIへの条件付きおよび制限アクセスを提供するフローを定義します。簡単に言えば、サード・パーティのアプリケーションは、まずファースト・パーティに登録する必要があり、その後、ファースト・パーティ(またはファースト・パーティのRESTfulサービスのエンド・ユーザー)が、そのサード・パーティ・アプリケーションに対する期限の短いアクセス・トークンを発行することで、サード・パーティ・アプリケーションのRESTful APIへの制限付きアクセスを承認します。
関連項目:
ietf_rfc6749
4.3.1.2.1 Two-LeggedおよびThree-LeggedのOAuthフロー
OAuth内の一部のフローはTwo-Leggedで、その他のフローはThree-Leggedで定義されています。
Two-Legged OAuthのフローには、RESTful APIを呼び出すパーティ(サード・パーティ・アプリケーション)、およびRESTful APIを提供するパーティの2つのパーティが関与します。Two-Leggedのフローは、エンド・ユーザーがRESTful APIへのアクセスを承認する必要はなく、サーバーとサーバー間の相互作用に使用されます。OAuth 2.0では、このフローはクライアント資格証明フローと呼ばれます。これは、最も典型的には、企業間取引(business to business)のシナリオで使用されます。
Three-Legged OAuthのフローには、RESTful APIを呼び出すパーティ、RESTful APIを提供するパーティ、およびRESTful APIによりアクセスを行うデータを所有または管理しているエンド・ユーザー・パーティの3つのパーティが関与します。Three-Leggedのフローは、エンド・ユーザーがRESTful APIへのアクセスを承認する必要のある、クライアントとサーバーの相互作用に使用されます。OAuth 2.0では、認可コードのフローおよび暗黙のフローはThree-Leggedフローです。これらのフローは、通常、企業と消費者間の取引(business to consumer)シナリオで使用されます。
Three-Leggedフローによって保護されたリソースでは、OAuthのクライアントがRESTful APIに登録されている場合、アクセスを必要とする保護されたリソースを安全に示すことができ、クライアントのアクセスを許可するかどうかの最終的な承認の決定権をエンド・ユーザーが持ちます。しかし、Two-Leggedフローによって保護されたリソースでは、各クライアントにどのリソースへのアクセスを認可するかをRESTful APIの所有者が承認する必要があります。
4.3.2 リソースにアクセスするための権限について
リソースにアクセスするための権限は、次のデータで構成されます。
-
名前: 権限の一意の識別子。この値は必須です。
-
ラベル: OAuthを使用してユーザーが権限へのアクセスを承認するように求められるとき、エンド・ユーザーに提示される権限の名前。権限がThree-LeggedのOAuthフローで使用される場合、この値は必須です。
-
説明: 権限の目的の説明。これも、ユーザーが権限へのアクセスを承認するように求められるとき、エンド・ユーザーに提示されます。権限がThree-LeggedのOAuthフローで使用される場合、この値は必須です。
-
ロール: 権限に関連付けられているロール名のセット。認証されたパーティは、権限で保護されたリソースへのアクセスを許可されるために、指定されたロールの少なくとも1つを持っている必要があります。値は必須ですが、空のセットとすることはでき、それはユーザーの認証は必要だが、権限にアクセスするための特定のロールは必要ないことを示します。
Two-LeggedのOAuthフローでは、サード・パーティのアプリケーション(OAuthの用語ではクライアントと呼ばれる)は、必要なロールの少なくとも1つを持つ必要があります。
Three-LeggedのOAuthフローでは、サード・パーティのアプリケーションからのアクセス・リクエストを承認するエンド・ユーザーは、必要なロールの少なくとも1つを持つ必要があります。
4.3.3 リソースにアクセスするためのユーザーおよびロールについて
権限は一連のロールを列挙し、ユーザーはロールを持つことはできますが、これらのロールはどこに定義されるのでしょう。ロールを持っているユーザーについてはどうでしょう。彼らはどこに定義されているのでしょう。
権限は一連のロールを列挙し、ユーザーはロールを持つことができます。Oracle REST Data Servicesは、ユーザー管理のタスクをOracle REST Data Servicesがデプロイされているアプリケーション・サーバーに委任します。Oracle REST Data Servicesでは、アプリケーション・サーバーによって定義および管理されるユーザーを認証でき、認証されたユーザーが所属するロールおよびグループを識別できます。アプリケーション・サーバーのユーザー・リポジトリを構成することも、アプリケーション・サーバーにOracle REST Data Servicesをデプロイするパーティの責任です。
ユーザー・リポジトリを定義したり、既存のユーザー・リポジトリと統合したり、アプリケーション・サーバーはいろいろな方法で構成できるため、アプリケーション・サーバーのユーザー・リポジトリを構成する方法はこのドキュメントでは説明できません。詳細は、アプリケーション・サーバーのドキュメントを参照してください。
4.3.4 ファイルベースのユーザー・リポジトリについて
Oracle REST Data Servicesでは、簡易なファイルベースのユーザー・リポジトリ・メカニズムが提供されます。ただし、このユーザー・リポジトリはデモおよびテストのみを目的としており、本番使用はサポートされていません。
このリポジトリにユーザーを作成する方法の詳細は、次のように、ユーザー・コマンドのコマンドライン・ヘルプを参照してください。
java -jar ords.war help user
形式:
java -jar ords.war user <user> <roles>
引数:
-
<user>
はユーザーのユーザーIDです。 -
<roles>
はユーザーが持つロール(ゼロ以上)のリストです。
関連トピック
4.3.5 チュートリアル: リソースの保護およびアクセス
このチュートリアルでは、次のOAuth機能を使用し、リソースのセットを保護するための権限を作成し、保護されたリソースにアクセスする方法を示します。
-
クライアント資格証明
-
認可コード
-
暗黙のフロー
また、ファースト・パーティCookieベースの認証を使用してリソースにアクセスする方法を示します。
トピック:
4.3.5.1 OAuthフローと各フローの用途
この項では、様々なOAuthフロー機能の用途を説明します。
ファースト・パーティCookieベースの認証は、RESTful APIと同じオリジンでホストされるWebアプリケーションからRESTful APIにアクセスするときに使用します。
認可コード・フローは、RESTful APIにアクセスするサード・パーティのWebアプリケーションを許可する必要があり、そのサード・パーティ・アプリケーションが、安全にクライアントの資格証明を保持できる独自のWebサーバーを持っている場合に使用します。これは、ほとんどのWebアプリケーションの標準的な状況で、サード・パーティのアプリケーションは、アプリケーションの再認証をユーザーに促すことなく、リフレッシュ・トークンを使用してユーザー・セッションの存続期間を延長でき、最高のセキュリティと最高のユーザー・エクスペリエンスを提供できます。
暗黙のフローは、サード・パーティのアプリケーションがその資格証明を安全に保持できるWebサーバーを持たない場合に使用します。このフローは、サード・パーティの単一ページ・ベースのアプリケーションで役立ちます。暗黙のフローではリフレッシュ・トークンを発行できないので、ユーザーはアプリケーションを認証するように頻繁に促されます。
ネイティブ・モバイルやデスクトップのアプリケーションは、認可コードまたは暗黙のフローを使用する必要があります。それらは、Webブラウザの画面にサイン・インおよび認可のプロンプトを表示し、認可処理の最後にWebブラウザの画面からアクセス・トークンを取得する必要があります。
クライアント資格証明フローは、RESTful APIによって管理されるデータへのアクセスを承認するようにユーザーに要求せず、サード・パーティのアプリケーションにRESTful APIへの直接アクセスを提供する必要がある場合に使用します。このサード・パーティのアプリケーションは、資格証明の機密を保持できるサーバー・ベースのアプリケーションである必要があります。クライアント資格証明はいつでもネイティブの実行可能ファイル内で検出できるため、クライアント資格証明フローはネイティブ・アプリケーションでは使用しないでください。
4.3.5.2 このチュートリアルの前提
このチュートリアルでは、次のことが前提となっています。
-
Oracle REST Data Servicesは、次のURLにデプロイされています:
https://example.com/ords/
-
ORDSTESTという名前のデータベース・スキーマがOracle REST Data Servicesで使用するために有効になっており、そのRESTful APIが次の場所で公開されています:
https://example.com/ords/ordstest/
-
ORDSTESTスキーマには、次のように作成されたEMPという名前のデータベース表があります。
create table emp ( empno number(4,0), ename varchar2(10 byte), job varchar2(9 byte), mgr number(4,0), hiredate date, sal number(7,2), comm number(7,2), deptno number(2,0), constraint pk_emp primary key (empno) );
-
保護するリソースは次の場所にあります:
https://example.com/ords/ordstest/examples/employees/
4.3.5.3 このチュートリアルのステップ
リソースのセットを保護してアクセスするには、次のステップを実行します。
-
スキーマを有効にします。ORDSTESTスキーマに接続し、次のPL/SQL文を実行します。
begin ords.enable_schema; commit; end;
-
リソースを作成します。ORDSTESTスキーマに接続し、次のPL/SQL文を実行します。
begin ords.create_service( p_module_name => 'examples.employees' , p_base_path => '/examples/employees/', p_pattern => '.' , p_items_per_page => 7, p_source => 'select * from emp order by empno desc'); commit; end;
このコードにより、この後のステップで権限で保護する
/examples/employees/
リソースが作成されます。次のようにcURLコマンドを実行して、リソースを確認できます。
curl -i https://example.com/ords/ordstest/examples/employees/
結果は次のようになるはずです(読みやすくするために編集しています)。
Content-Type: application/json Transfer-Encoding: chunked { "items": [ {"empno":7934,"ename":"MILLER","job":"CLERK","mgr":7782,"hiredate":"1982-01-23T00:00:00Z","sal":1300,"comm":null,"deptno":10}, ... ], "hasMore":true, "limit":7, "offset":0, "count":7, "links": [ {"rel":"self","href":"https://example.com/ords/ordstest/examples/employees/"}, {"rel":"describedby","href":"https://example.com/ords/ordstest/metadata-catalog/examples/employees/"}, {"rel":"first","href":"https://example.com/ords/ordstest/examples/employees/"}, {"rel":"next","href":"https://example.com/ords/ordstest/examples/employees/?offset=7"} ] }
-
権限を作成します。ORDSTESTスキーマに接続し、次のPL/SQL文を実行します。
begin ords.create_role('HR Administrator'); ords.create_privilege( p_name => 'example.employees', p_role_name => 'HR Administrator', p_label => 'Employee Data', p_description => 'Provide access to employee HR data'); commit; end;
このコードにより、ORDSTESTスキーマに属するロールと権限が作成されます。
-
ロール名は一意である必要があり、印刷可能な文字のみを含める必要があります。
-
権限名は一意である必要があり、OAuth 2.0仕様の第3.3項のスコープ名で指定されている構文に準拠する必要があります。
-
Three-Leggedの認可コードおよび暗黙のフローでこの権限を使用する場合は、ラベルおよび権限の説明を用意する必要があります。このラベルおよび説明は、Three-Leggedフローの承認フェーズでエンド・ユーザーに提示されます。
-
値は、その権限の名前と目的を識別するプレーン・テキストである必要があります。
USER_ORDS_PRIVILEGESビューの問合せで、権限が正しく作成されたことを確認できます。
select id,name from user_ords_privileges where name = 'example.employees';
結果は次のようになるはずです。
ID NAME ----- ----------------- 10260 example.employees
IDの値はデータベースによって異なりますが、NAMEの値はこのように表示されるはずです。
-
-
権限をリソースと関連付けます。ORDSTESTスキーマに接続し、次のPL/SQL文を実行します。
begin ords.create_privilege_mapping( p_privilege_name => 'example.employees', p_pattern => '/examples/employees/*'); commit; end;
このコードは、
example.employees
権限を/examples/employees/
というリソース・パターンと関連付けます。USER_ORDS_PRIVILEGE_MAPPINGSビューの問合せで、権限が正しく作成されたことを確認できます。
select privilege_id, name, pattern from user_ords_privilege_mappings;
結果は次のようになるはずです。
PRIVILEGE_ID NAME PATTERN ------------ -------------------- --------------------- 10260 example.employees /examples/employees/*
PRIVILEGE_IDの値はデータベースによって異なりますが、NAMEおよびPATTERNの値はこのように表示されるはずです。
次のcURLコマンドを実行し、
/examples/employees/
リソースがexample.employees
権限で保護されていることを確認できます。curl -i https://example.com/ords/ordstest/examples/employees/
結果は次のようになるはずです(読みやすくするために再フォーマットしています)。
HTTP/1.1 401 Unauthorized Content-Type: text/html Transfer-Encoding: chunked <!DOCTYPE html> <html> ... </html>
保護されたリソースにファースト・パーティの認証を介してアクセスできることを、次の手順で確認できます。
-
エンド・ユーザーを作成します。ファイルベースのユーザー・リポジトリを使用して、
examples.employees
権限にアクセスするために必要なHR管理者のロールを持つテスト・ユーザーを作成します。コマンド・プロンプトで次のコマンドを実行します。java -jar ords.war user "hr_admin" "HR Administrator"
パスワードの入力を求められたら、入力し、確認します。
-
エンド・ユーザーとしてサイン・インします。Webブラウザに次のURLを入力します。
https://example.com/ords/ordstest/examples/employees/
アクセスが拒否されたことを示すページで、サイン・インへのリンクをクリックします。
HR_ADMINユーザーのために登録した資格証明を入力し、「サインイン」をクリックします。
ページが
https://example.com/ords/ordstest/examples/employees/
にリダイレクトされること、およびJSONドキュメントが表示されることを確認します。
-
-
OAuthクライアントを登録します。ORDSTESTスキーマに接続し、次のPL/SQL文を実行します。
begin oauth.create_client( p_name => 'Client Credentials Example', p_grant_type => 'client_credentials', p_privilege_names => 'example.employees', p_support_email => 'support@example.com'); commit; end;
このコードは、クライアント資格証明のOAuthフローを使用して
examples.employees
権限にアクセスする、Client Credentials Example
という名前のクライアントを登録します。次のSQL文を実行し、クライアントが登録されたこと、および
examples.employees
権限へのアクセスがリクエストされたことを確認できます。select client_id,client_secret from user_ords_clients where name = 'Client Credentials Example';
結果は次のようになるはずです。
CLIENT_ID CLIENT_SECRET -------------------------------- ------------------------ o_CZBVkEMN23tTB-IddQsQ.. 4BJXceufbmTki-vruYNLIg..
CLIENT_IDおよびCLIENT_SECRETの値は、OAuthクライアントの機密の資格証明を表します。これらの値は、記録して安全に保管する必要があります。これは、クライアント・アプリケーションのユーザーIDおよびパスワードと考えることができます。
-
OAuthクライアントに必要な権限を付与します。ORDSTESTスキーマに接続し、次のPL/SQL文を実行します。
begin oauth.grant_client_role( 'Client Credentials Example', 'HR Administrator'); commit; end;
このコードは、クライアント資格証明のOAuthフローを使用して
examples.employees
権限にアクセスする、Client Credentials Example
という名前のクライアントを登録します。次のSQL文を実行することで、クライアントにロールが付与されたことを確認できます。
select * from user_ords_client_roles where client_name = 'Client Credentials Example';
結果は次のようになるはずです。
CLIENT_ID CLIENT_NAME ROLE_ID ROLE_NAME ---------- --------------------------- -------- ---------------------- 10286 Client Credentials Example 10222 HR Administrator
-
クライアントの資格証明を使用してのOAuthのアクセス・トークンを取得します。
OAuthプロトコルでは、HTTPリクエストに、クライアント資格証明フローを使用して作成したアクセス・トークンを使用しなければならないと明記されています。[rfc6749-4.4.]。
リクエストは、トークン・エンドポイントと呼ばれる、周知のURLとして作成する必要があります。Oracle REST Data Servicesのトークン・エンドポイントのパスは常にoauth/tokenで、アクセスされるスキーマのルート・パスからの相対です。この例のトークン・エンドポイントは次のとおりです。
https://example.com/ords/ordstest/oauth/token
次のcURLコマンドを実行します。
curl -i --user clientId:clientSecret --data "grant_type=client_credentials" https://example.com/ords/ordstest/oauth/token
このコマンドで、
clientId
をClient Credentials Example
のUSER_ORDS_CLIENTS内のCLIENT_IDの値で置き換え、clientSecret
をClient Credentials Example
のUSER_ORDS_CLIENTS内のCLIENT_SECRETの値で置き換えます。出力は次のようになります。HTTP/1.1 200 OK Content-Type: application/json { "access_token": "2YotnFZFEjr1zCsicMWpAA", "token_type": "bearer", "expires_in":3600 }
この出力では、アクセス・トークンは
bearer
タイプで、その値はaccess_token
フィールドで指定されています。この値はリクエストごとに異なります。expires_in
の値は、アクセス・トークンの有効期限が切れるまでの秒数を示し、この例のトークンは1時間(3600秒)で期限切れになります。 -
アクセス・トークンを使用して保護されたリソースにアクセスします。次のcURLコマンドを実行します。
curl -i -H"Authorization: Bearer accessToken" https://example.com/ords/ordstest/examples/employees/
このコマンドで、
accessToken
が前のステップで示したaccess_token
フォールドの値で置き換えられます。出力は次のようになります。Content-Type: application/json Transfer-Encoding: chunked { "items": [ {"empno":7934,"ename":"MILLER","job":"CLERK","mgr":7782,"hiredate":"1982-01-23T00:00:00Z","sal":1300,"comm":null,"deptno":10}, ... ], "hasMore":true, "limit":7, "offset":0, "count":7, "links": [ {"rel":"self","href":"https://example.com/ords/ordstest/examples/employees/"}, {"rel":"describedby","href":"https://example.com/ords/ordstest/metadata-catalog/examples/employees/"}, {"rel":"first","href":"https://example.com/ords/ordstest/examples/employees/"}, {"rel":"next","href":"https://example.com/ords/ordstest/examples/employees/?offset=7"} ] }
-
認可コード用のクライアントを登録します。ORDSTESTスキーマに接続し、次のPL/SQL文を実行します。
begin oauth.create_client( p_name => 'Authorization Code Example', p_grant_type => 'authorization_code', p_owner => 'Example Inc.', p_description => 'Sample for demonstrating Authorization Code Flow', p_redirect_uri => 'http://example.org/auth/code/example/', p_support_email => 'support@example.org', p_support_uri => 'http://example.org/support', p_privilege_names => 'example.employees' ); commit; end;
このコードは、認可コードのOAuthフローを使用して
examples.employees
権限にアクセスする、Authorization Code Example
という名前のクライアントを登録します。実際のアプリケーションでは、認可コードをリダイレクトして戻すURIを用意する必要があり、有効なサポート電子メール・アドレスを指定する必要があります。この例では、架空のデータおよびサンプルのWebサービスexample.org
を使用しています。次のSQL文を実行し、クライアントが登録されたこと、および
examples.employees
権限へのアクセスがリクエストされたことを確認できます。select id, client_id, client_secret from user_ords_clients where name = 'Authorization Code Example';
結果は次のようになるはずです。
ID CLIENT_ID CLIENT_SECRET ---------- -------------------------------- -------------------------------- 10060 IGHso4BRgrBC3Jwg0Vx_YQ.. GefAsWv8FJdMSB30Eg6lKw..
権限へのアクセス権を付与するには、エンド・ユーザーがアクセスを承認する必要があります。CLIENT_IDおよびCLIENT_SECRETの値は、OAuthクライアントの機密の資格証明を表します。これらの値は、記録して安全に保管する必要があります。これは、クライアント・アプリケーションのユーザーIDおよびパスワードと考えることができます。
-
認可コードを使用してOAuthアクセス・トークンを取得します。このステップには、いくつかのサブ・ステップがあります。(前のステップでHR_ADMINエンド・ユーザーを作成しておく必要があります。)
-
OAuth認可コードを取得します。
エンド・ユーザーには、サイン・インおよびサード・パーティ・アプリケーションへのアクセスを承認するためのプロンプトを表示する(Webページを介して)必要があります。サード・パーティ・アプリケーションは、OAuthの認可エンドポイントにユーザーを誘導することによってこのプロセスを開始します。Oracle REST Data Servicesの認可エンドポイントのパスは常に
oauth/auth
で、アクセスされるスキーマのルート・パスからの相対です。この例のトークン・エンドポイントは次のとおりです。https://example.com/ords/ordstest/oauth/auth
OAuth 2.0プロトコルでは、認可リクエストのURIに、問合せ文字列に特定のパラメータを含める必要があると明記されています。
response_type
パラメータには、code
の値が必要です。client_id
パラメータには、アプリケーションのクライアント識別子の値が含まれている必要があります。これは前のステップで決定したclient_id
の値です。state
パラメータには、一意の推測できない値が含まれている必要があります。この値には、2つの目的があります。それは、クライアント・アプリケーションが各認可リクエストを一意に識別する方法を提供すること(それにより、任意のアプリケーション固有の状態を値に関連付け、その値をアプリケーション自身のセッション識別子と考える)、およびクライアント・アプリケーションがクロス・サイト・リクエスト・フォージェリ(CSRF)攻撃から身を守る手段を提供することです。state
の値は、認可プロセスの最後にリダイレクトURIに戻されます。クライアントは、その値がアプリケーションによって開始された認可リクエストのものであることを確認する必要があります。クライアントが状態の値を検証できない場合は、認可リクエストが攻撃者によって開始されたものとみなし、リダイレクトを無視してください。認可リクエストを開始するには、Webブラウザで次のURLを入力します。
https://example.com/ords/ordstest/oauth/auth?response_type=code&client_id=cliendId&state=uniqueRandomValue
このURIは、
clientId
を以前に注目したCLIENT_ID列の値と置き換え、uniqueRandromValue
を一意の推測できない値に置き換えます。クライアント・アプリケーションは、この値を記憶し、認可フローの最後にリダイレクトの一部として戻されるstate
パラメータと照合する必要があります。client_id
が認識された場合、サイン・インのプロンプトが表示されます。エンド・ユーザーHR_ADMINの資格証明を入力して「サインイン」をクリックし、次のページで「承認」をクリックすると、クライアントが登録されたときに指定したリダイレクトURIへリダイレクトされます。リダイレクトURIは、URIの問合せ文字列部分に認可コードが含まれます。また、クライアントがフローの開始時に指定したものと同じstate
パラメータの値が含まれます。リダイレクトURIは次のようになります。http://example.org/auth/code/example/?code=D5doeTSIDgbxWiWkPl9UpA..&state=uniqueRandomValue
クライアント・アプリケーションは、
state
パラメータの値を検証し、アクセス・トークンの取得に使用するcode
パラメータの値を記録する必要があります。 -
OAuthのアクセス・トークンを取得します。
サード・パーティ・アプリケーションは、認可コードを取得した後、それをアクセス・トークンと交換する必要があります。サード・パーティ・アプリケーションのサーバーは、トークン・エンドポイントにHTTPSリクエストを行う必要があります。次の例のようにcURLコマンドを使用して、このリクエストを行うサーバーを模倣できます。
curl --user clientId:clientSecret --data "grant_type=authorization_code&code=authorizationCode" https://example.com/ords/ordstest/oauth/token
このコマンドで、
clientId
をAuthorization Code Example
のUSER_ORDS_CLIENTSにあるCLIENT_IDの値と置き換え、clientSecret
をAuthorization Code Example
のUSER_ORDS_CLIENTSにあるCLIENT_SECRETの値と置き換え、authorizationCode
を前のステップで記録した認可コードの値(code
パラメータの値)と置き換えます。結果は次のようになるはずです。
HTTP/1.1 200 OK Content-Type: application/json { "access_token": "psIGSSEXSBQyib0hozNEdw..", "token_type": "bearer", "expires_in":3600, "refresh_token": "aRMg7AdWPuDvnieHucfV3g.." }
この結果では、アクセス・トークンが
access_token
フィールドで指定され、リフレッシュ・トークンがrefresh_token
フィールドで指定されています。このリフレッシュ・トークンの値は、ユーザーにサード・パーティ・アプリケーションの再認可を求めることなく、ユーザー・セッションを延長するために使用できます。 -
アクセス・トークンを使用して保護されたリソースにアクセスします。
サード・パーティ・アプリケーションでは、OAuthのアクセス・トークンを取得した後、そのアクセス・トークンを使用して保護された
/examples/employees/
リソースにアクセスできます。curl -i -H"Authorization: Bearer accessToken" https://example.com/ords/ordstest/examples/employees/
このコマンドで、
accessToken
が前のステップで示したaccess_token
フォールドの値で置き換えられます。結果は次のようになるはずです。
Content-Type: application/json Transfer-Encoding: chunked { "items": [ {"empno":7934,"ename":"MILLER","job":"CLERK","mgr":7782,"hiredate":"1982-01-23T00:00:00Z","sal":1300,"comm":null,"deptno":10}, ... ], "hasMore":true, "limit":7, "offset":0, "count":7, "links": [ {"rel":"self","href":"https://example.com/ords/ordstest/examples/employees/"}, {"rel":"describedby","href":"https://example.com/ords/ordstest/metadata-catalog/examples/employees/"}, {"rel":"first","href":"https://example.com/ords/ordstest/examples/employees/"}, {"rel":"next","href":"https://example.com/ords/ordstest/examples/employees/?offset=7"} ] }
-
リフレッシュ・トークンを使用してセッションを延長します。
サード・パーティ・アプリケーションは、いつでも、リフレッシュ・トークンの値を使用して新規の存続期間を持つ新規のアクセス・トークンを生成できます。これにより、サード・パーティ・アプリケーションは自由にユーザー・セッションを延長できます。このためには、サード・パーティ・アプリケーションのサーバーは、トークン・エンドポイントにHTTPSリクエストを行う必要があります。次の例のようにcURLコマンドを使用して、このリクエストを行うサーバーを模倣できます。
curl --user clientId:clientSecret --data “grant_type=refresh_token&refresh_token=refreshToken" https://example.com/ords/ordstest/oauth/token
このコマンドで、
clientId
をClient Credentials Client
のUSER_ORDS_CLIENTSにあるCLIENT_IDの値と置き換え、clientSecret
をClient Credentials Client
のUSER_ORDS_CLIENTSにあるCLIENT_SECRETの値と置き換え、refreshToken
を前のステップで取得したrefresh_token
の値と置き換えます。結果は次のようになるはずです。
HTTP/1.1 200 OK Content-Type: application/json { "access_token": "psIGSSEXSBQyib0hozNEdw..", "token_type": "bearer", "refresh_token": "aRMg7AdWPuDvnieHucfV3g..", "expires_in": 3600 }
この結果では、アクセス・トークンが
access_token
フィールドで指定され、新規リフレッシュ・トークンがrefresh_token
フィールドで指定されています。このリフレッシュ・トークンの値は、ユーザーにサード・パーティ・アプリケーションの再認可を求めることなく、ユーザー・セッションを延長するために使用できます。(前のアクセス・トークンおよびリフレッシュ・トークンは無効となり、そのかわりに新規の値を使用する必要があることに注意してください。)
-
-
暗黙のフローのクライアントを登録します。ORDSTESTスキーマに接続し、次のPL/SQL文を実行します。
begin oauth.create_client( p_name => 'Implicit Example', p_grant_type => 'implicit', p_owner => 'Example Inc.', p_description => 'Sample for demonstrating Implicit Flow', p_redirect_uri => 'http://example.org/implicit/example/', p_support_email => 'support@example.org', p_support_uri => 'http://example.org/support', p_privilege_names => 'example.employees' ); commit; end;
このコードは、暗黙のOAuthフローを使用して
examples.employees
権限にアクセスする、Implicit Example
という名前のクライアントを登録します。実際のアプリケーションでは、認可コードをリダイレクトして戻すURIを用意する必要があり、有効なサポート電子メール・アドレスを指定する必要があります。この例では、架空のデータおよびサンプルのWebサービスexample.org
を使用しています。次のSQL文を実行し、クライアントが登録されたこと、および
examples.employees
権限へのアクセスがリクエストされたことを確認できます。select id, client_id, client_secret from user_ords_clients where name = 'Implicit Example';
結果は次のようになるはずです。
ID CLIENT_ID CLIENT_SECRET ---------- -------------------------------- -------------------------------- 10062 7Qz--bNJpFpv8qsfNQpS1A..
権限へのアクセス権を付与するには、エンド・ユーザーがアクセスを承認する必要があります。
-
暗黙のフローを使用してのOAuthのアクセス・トークンを取得します。(前のステップでHR_ADMINエンド・ユーザーを作成しておく必要があります。)
エンド・ユーザーには、サイン・インおよびサード・パーティ・アプリケーションへのアクセスを承認するためのプロンプトを表示する(Webページを介して)必要があります。サード・パーティ・アプリケーションは、OAuthの認可エンドポイントにユーザーを誘導することによってこのプロセスを開始します。Oracle REST Data Servicesの認可エンドポイントのパスは常に
oauth/auth
で、アクセスされるスキーマのルート・パスからの相対です。この例のトークン・エンドポイントは次のとおりです。https://example.com/ords/ordstest/oauth/auth
OAuth 2.0プロトコルでは、認可リクエストのURIに、問合せ文字列に特定のパラメータを含める必要があると明記されています。
response_type
パラメータには、token
の値が必要です。client_id
パラメータには、アプリケーションのクライアント識別子の値が含まれている必要があります。これは前のステップで決定したclient_id
の値です。state
パラメータには、一意の推測できない値が含まれている必要があります。この値には、2つの目的があります。それは、クライアント・アプリケーションが各認可リクエストを一意に識別する方法を提供すること(それにより、任意のアプリケーション固有の状態を値に関連付け、その値をアプリケーション自身のセッション識別子と考える)、およびクライアント・アプリケーションがクロス・サイト・リクエスト・フォージェリ(CSRF)攻撃から身を守る手段を提供することです。state
の値は、認可プロセスの最後にリダイレクトURIに戻されます。クライアントは、その値がアプリケーションによって開始された認可リクエストのものであることを確認する必要があります。クライアントが状態の値を検証できない場合は、認可リクエストが攻撃者によって開始されたものとみなし、リダイレクトを無視してください。認可リクエストを開始するには、Webブラウザで次のURLを入力します。
https://example.com/ords/ordstest/oauth/auth?response_type=token&client_id=cliendId&state=uniqueRandomValue
このURIは、
clientId
を以前に注目したCLIENT_ID列の値と置き換え、uniqueRandromValue
を一意の推測できない値に置き換えます。クライアント・アプリケーションは、この値を記憶し、認可フローの最後にリダイレクトの一部として戻されるstate
パラメータと照合する必要があります。client_id
が認識された場合、サイン・インのプロンプトが表示されます。エンド・ユーザーHR_ADMINの資格証明を入力して「サインイン」をクリックし、次のページで「承認」をクリックすると、クライアントが登録されたときに指定したリダイレクトURIへリダイレクトされます。リダイレクトURIは、URIの問合せ文字列部分にアクセス・トークンが含まれます。また、クライアントがフローの開始時に指定したものと同じstate
パラメータの値が含まれます。リダイレクトURIは次のようになります。http://example.org/auth/code/example/#access_token=D5doeTSIDgbxWiWkPl9UpA..&type=bearer&expires_in=3600&state=uniqueRandomValue
クライアント・アプリケーションは、
state
パラメータの値を検証し、そのアクセス・トークンの値をメモする必要があります。 -
アクセス・トークンを使用して保護されたリソースにアクセスします。次のcURLコマンドを実行します。
curl -i -H "Authorization: Bearer accessToken" https://example.com/ords/ordstest/examples/employees/
このコマンドで、
accessToken
が前のステップで示したaccess_token
フォールドの値で置き換えられます。出力は次のようになります。Content-Type: application/json Transfer-Encoding: chunked { "items": [ {"empno":7934,"ename":"MILLER","job":"CLERK","mgr":7782,"hiredate":"1982-01-23T00:00:00Z","sal":1300,"comm":null,"deptno":10}, ... ], "hasMore":true, "limit":7, "offset":0, "count":7, "links": [ {"rel":"self","href":"https://example.com/ords/ordstest/examples/employees/"}, {"rel":"describedby","href":"https://example.com/ords/ordstest/metadata-catalog/examples/employees/"}, {"rel":"first","href":"https://example.com/ords/ordstest/examples/employees/"}, {"rel":"next","href":"https://example.com/ords/ordstest/examples/employees/?offset=7"} ] }
4.4 Oracle REST Data Servicesのユーザー・ロールについて
Oracle REST Data Servicesでは、少数のユーザー・ロールが事前定義されています。
-
RESTful Services
- 保護されたRESTfulサービスに関連付けられたデフォルトのロールです。 -
OAuth2 Client Developer
- OAuth 2.0のアプリケーションを登録するユーザーはこのロールが必要です。 -
oracle.dbtools.autorest.any.schema
- すべてのAutoRESTサービスにアクセスするユーザー。 -
SQL Developer
- Oracle SQL Developerを使用してRESTfulサービスを開発するユーザーはこのロールが必要です。 -
SODA Developer
- これは、SODA REST APIにアクセスする必要があるデフォルト・ロールです。このロールの詳細は、『Oracle REST Data Services SODA for REST開発者ガイド』を参照してください。 -
Listener Administrator
- Oracle SQL Developerを介してOracle REST Data Servicesのインスタンスを管理するユーザーはこのロールが必要です。通常、java -jar ords.war user
コマンドによって作成されたユーザーのみがこのロールを持ちます。Listener Administrator
ロールによりOracle REST Data Servicesのインスタンスを構成でき、その結果、そのインスタンスで処理されるすべてのApplication Expressのワークスペースに影響を与えることが可能となるため、Application ExpressユーザーはListener Administrator
ロールを取得することを許可されません。
トピック:
4.4.1 Oracle Application ExpressのユーザーとOracle REST Data Servicesのロールについて
デフォルトでは、Oracle Application ExpressのユーザーはOracle REST Data Servicesの事前定義済ユーザー・ロールを持っていません。これは、デフォルトでは、Application Expressのユーザーは次のことができないことを意味します。
-
保護されたRESTfulサービスの起動
-
OAuth 2.0アプリケーションの登録
-
Oracle SQL Developerを使用したRESTfulサービスの開発
これは、Application Expressの開発者および管理者を含め、すべてのApplication Expressユーザーに適用されます。そこで、Application Expressのユーザーを適切なユーザー・グループに追加して前述のアクションを実行できるようにするため、次のステップに従うことを覚えておくことが重要です。
トピック:
4.4.1.1 Application ExpressユーザーにOracle REST Data Servicesロールを付与する
Application Expressユーザーに前述のロールのいずれかを付与するには、ユーザーをロールに対応するApplication Expressのユーザー・グループに追加する必要があります。たとえば、RESTEASY_ADMIN
ユーザーにRESTful Services
ロールを付与するには、次のステップを実行します。
RESTEASY_ADMIN
でRESTEASY
ワークスペースにログインします。- 「管理」に移動し、「ユーザーとグループの管理」に移動します。
RESTEASY_ADMIN
ユーザーの左にある編集アイコンをクリックします。- 「ユーザー・グループ」で、
「RESTfulサービス」
を選択します。 - 「変更の適用」をクリックします。
4.4.1.2 Application Expressユーザーに自動的にOracle REST Data Servicesロールを付与する
Application Expressユーザーを適切なユーザー・グループに追加するのは、ステップを見落としがちで、管理するユーザーが多い場合は反復的なタスクとなります。
この問題に対処するため、defaults.xml
構成ファイルを変更し、Application Expressユーザーに自動的に事前定義済のRESTfulサービス・ロールのセットを付与するようにOracle REST Data Servicesを構成できます。
このファイルには、Oracle REST Data Servicesがロールを構成するための3つのプロパティ設定が定義されています。
-
apex.security.user.roles
- 開発者または管理者ではない通常のユーザーに付与するロールのカンマ区切りのリスト。 -
apex.security.developer.roles
-Developer
アカウントの権限を持つユーザーに付与するロールのカンマ区切りのリスト。Developer
は、apex.security.user.roles
設定で定義されているロールも継承します。 -
apex.security.administrator.roles
-Administrator
アカウントの権限を持つユーザーに付与するロールのカンマ区切りのリスト。Administrator
は、apex.security.user.roles
およびapex.security.developer.roles
設定で定義されているロールも継承します。
たとえば、自動的に、すべてのユーザーにRESTful Services
権限を付与し、すべての開発者および管理者にOAuth2 Client Developer
およびSQL Developer
ロールを付与するには、defaults.xml
構成ファイルに次のように追加します。
<!-- Grant all Application Express Users the ability to invoke protected RESTful Services --> <entry key="apex.security.user.roles">RESTful Services</entry> <!-- Grant Application Express Developers and Administrators the ability to register OAuth 2.0 applications and use Oracle SQL Developer to define RESTful Services --> <entry key="apex.security.developer.roles"> OAuth2 Client Developer, SQL Developer</entry>
defaults.xml
構成ファイルを変更したら、Oracle REST Data Servicesを再起動する必要があります。
4.4.2 ロールによるRESTfulサービスのアクセス制御
組込みのRESTful Service
ロールは、保護されたRESTfulサービスにアクセスすることを許可されたユーザーの識別に役立つデフォルトです。
しかし、特定のRESTfulサービスにアクセスできるユーザーのセットを制限するため、きめ細かいロール定義が必要になることもあります。
トピック:
4.4.2.1 RESTfulサービスのロールの定義について
RESTfulサービスのロールは、Application Expressのユーザー・グループです。ギャラリRESTfulサービスへのアクセスを制御するためにユーザー・グループを作成するには、次のステップに従います。 (
-
ワークスペース管理者として
RESTEASY
ワークスペースにログインします。 -
「管理」に移動し、「ユーザーとグループの管理」に移動します。
-
「グループ」タブをクリックします。
-
「ユーザー・グループの作成」をクリックします。
-
「名前」に
Gallery Users
と入力します。 -
「グループの作成」をクリックします。
4.4.2.2 ロールとRESTful権限の関連付け
ユーザー・グループを作成したら、それをRESTful権限と関連付けることができます。ギャラリ・ユーザーのロールをexample.gallery
権限に関連付けるには、次のステップに従います。
- 「SQLワークショップ」に移動し、「RESTfulサービス」に移動します。
- タスクのセクションで、RESTfulサービスの権限をクリックします。
- 「ギャラリ・アクセス」をクリックします。
- 「割当済グループ」で、
ギャラリ・ユーザー
を選択します。 - 「変更の適用」をクリックします。
この変更で、ユーザーはギャラリRESTfulサービスにアクセスできるギャラリ・ユーザー・ロールを持ちます。
関連項目:
このステップでは、例として「イメージ・ギャラリの作成」のイメージ・ギャラリ・アプリケーションを使用します。4.5 WebLogic Serverのユーザー・リポジトリに対する認証
Oracle REST Data Servicesでは、WebLogic Serverによって提供されるAPIを使用し、資格証明(ユーザー名とパスワード)を検証し、ユーザーがメンバーであるグループおよびロールのセットを取得できます。
この項では、WebLogic Serverによって提供される組込みのユーザー・リポジトリでユーザーを作成し、そのユーザーに対して認証を行う機能を検証します。
このドキュメントではWebLogic ServerをLDAPリポジトリなどの多くの一般的なユーザー・リポジトリ・システムと統合する方法は説明しませんが、WebLogic Serverが正しく構成されていれば、Oracle REST Data Servicesでそのようなリポジトリに対して認証が可能です。アプリケーション・サーバーでどのようなユーザー・リポジトリがサポートされているか、およびそれらのリポジトリへのアクセスを構成する方法の詳細は、アプリケーション・サーバーのドキュメントを参照してください。
トピック:
4.5.1 WebLogic Serverに対する認証
WebLogic Serverに対してのユーザー認証には、大きなステップとして次のものがあります。
4.5.1.1 WebLogic Serverユーザーの作成
サンプルのWebLogic Serverユーザーを作成するには、次のステップを実行します。
-
WebLogic Serverがまだ実行されていなければ、起動します。
-
WebLogic Server管理コンソール(通常は、
http://server:7001/console
)にアクセスし、資格証明を入力します。 -
左側のナビゲーション・ツリーで「セキュリティ・レルム」ノードをクリックします。
-
セキュリティ・レルムがすでに存在する場合は、次のステップに進みます。セキュリティ・レルムが存在しない場合は、次のようにして1つ作成します。
-
「新規」をクリックします。
-
「名前」に
Test-Realm
と入力し、「OK」をクリックします。 -
「Test-Realm」をクリックします。
-
「プロバイダ」タブをクリックします。
-
「新規」をクリックし、次の情報を入力します。
名前:
test-authenticator
タイプ:
DefaultAuthenticator
-
再起動が必要であると警告される場合は、WebLogic Serverを再起動します。
-
「Test-Realm」をクリックします。
-
-
「ユーザーとグループ」タブをクリックします。
-
「新規」をクリックし、次の情報を入力します。
-
名前:
3rdparty_dev2
-
「パスワード」: ユーザーの希望するパスワードを入力し、確認します。
-
-
「OK」をクリックします。
-
「グループ」タブをクリックします。
-
「新規」をクリックし、次の情報を入力します。
-
名前: OAuth2 Client Developer(大文字/小文字を区別)
-
-
「OK」をクリックします。
-
「ユーザー」タブをクリックします。
-
「3rdparty_dev2」ユーザーをクリックします。
-
「グループ」タブをクリックします。
-
「選択済み」リストに
OAuth2 Client Developer
を追加します。 -
「保存」をクリックします。
3rdparty_dev2
という名前のユーザーが作成され、OAuth2 Client Developer
という名前のグループのメンバーになります。これは、このユーザーがOAuth2 Client Developer
ロールを取得することを意味し、それによりOAuth 2.0アプリケーションの登録が許可されます。
では、ユーザーを正常に認証できることを検証します。
4.5.1.2 WebLogic Serverユーザーの検証
作成したWebLogic Serverユーザーが正常に認証されることを検証するには、次のステップを実行します。
アプリケーションが1つもリストされていない状態でOAuth 2.0クライアントの登録ページが表示されるはずです。このページが表示された場合は、WebLogic Serverのユーザー・リポジトリに対する認証が機能していることを検証できたことになります。
「ユーザーには、リソースにアクセスする権限がありません。」
というメッセージとともにサインオンのプロンプトが再表示される場合は、誤りを犯しています(おそらく、グループ・リストの値のスペルミス)。
4.6 既存のグループ/ロール・モデルとの統合
他の項の例で、WebLogic Serverの組込みのユーザー・リポジトリの構成方法を説明しています。そのような状況では、ユーザー・グループの名前の付け方を完全に制御できます。ユーザーがロールとまったく同じ(大文字/小文字を区別)名前を持つグループのメンバーである場合、そのユーザーはそのロールを持っていると考えられます。
しかし、既存のユーザー・リポジトリと統合する場合は、RESTfulサービスの開発者がユーザー・リポジトリ内のユーザー・グループの命名や編成を制御できないことがあります。このような状況では、ユーザー・リポジトリに定義された既存の「物理」ユーザーグループをOracle REST Data ServicesまたはRESTfulサービス(あるいはその両方)で定義された「論理」ロールにマッピングするメカニズムが必要とされます。
このグループからロールへのマッピングは、Oracle REST Data Servicesではrole-mapping.xml
という名前の構成ファイルを構成することで実現されます。
トピック:
4.6.1 role-mapping.xml
について
role-mapping.xml
は、各プロパティ・キーにユーザー・グループのセットに一致するパターンを定義し、そのプロパティ値で一致したユーザー・グループにマッピングされるロールを示すJava XMLプロパティ・ファイルです。これは、defaults.xml
構成ファイルと同じフォルダに配置する必要があります。ファイルは手動で作成して編集する必要があります。
次の例を考えてみます。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> <properties> <entry key="webdevs">RESTful Services</entry> </properties>
このロール・マッピングは単純で、webdevs
グループのメンバーであるすべてのユーザーにRESTful Services
ロールが付与され、それはwebdevs
グループのすべてのメンバーがRESTful Services
を起動できることを意味します。
1つのマッピングで、グループに複数のロールを適用できます。次に例を示します。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> <properties> <entry key="webdevs">RESTful Services, SQL Developer</entry> </properties>
この規則は、webdevs
グループにRESTful Services
およびSQL Developer
ロールの両方を付与します。
トピック:
4.6.1.1 マッピング・ルールのパラメータ化
グループまたはロールの数が多い場合には、各グループから各ロールに明示的にマッピングするのは拡張性がよくありません。この問題に対処するため、ルールをパラメータ化できます。次の例を考えてみます。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> <properties> <entry key="{prefix}.webdevs">RESTful Services</entry> </properties>
この例では、グループ名が.webdevs
で終わる任意のグループにRESTful Services
ロールがマッピングされます。たとえば、HQ.webdevs
という名前のグループは、EAST.webdevs
という名前のグループと同じようにこのルールに一致します。
ルールのパラメータを指定する構文はURIテンプレートに使用するものと同じで、パラメータ名が中カッコ({}
)で区切られます。
4.6.1.2 パラメータの間接参照
グループのルールで定義された任意のパラメータは、ロールのルールでも間接参照できます。次の例を考えてみます。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> <properties> <entry key="cn={userid},ou={group},dc=MyDomain,dc=com">{group}</entry> </properties>
この例では、LDAP識別名の組織単位コンポーネントをロールにマップします。つまり、組織単位の名前が同じ名前のロールに直接マッピングされるということです。{userid}
パラメータを参照しますが、実際にはそれが使用されていないことに注意してください。{userid}
は、ワイルドカードのフラグとして使用されています。
たとえば、識別名cn=jsmith,ou=Developers,dc=MyDomain,dc=com
は、Developers
という名前の論理ロールにマッピングされます。
4.6.1.3 間接マッピング
必要なロール・マッピングを実現するため、複数の中間的なルールの適用を必要とする場合もあります。次の例を考えてみます。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> <properties> <entry key="cn={userid},ou={group},dc=example,dc=com">{group}</entry> <entry key="{prefix},ou={group},dc=acquired,dc=com">{group}</entry> <entry key="Developers">RESTful Services, SQL Developer</entry> </properties>
この例では、LDAP識別名の組織単位コンポーネントをいくつかのロールにマップします。問題を複雑にしているのは、ユーザーは2つの異なる組織に属することがあり、その結果として識別名のパターンが異なるという事実です。
-
example.com
のユーザーは、必ず、彼らのユーザーIDを識別する単一の共通名(CN)を持ち、それに組織単位(OU)とドメイン名(DC)が続きます。たとえば、cn=jsmith,ou=Developers,dc=example,dc=com
です。 -
acquired.com
のユーザーの共通名(CN)接頭辞は様々ですが、ここで重要なのは組織単位のフィールドです。たとえば、cn=ProductDev,cn=abell,ou=Engineering,dc=acquired,dc=com
です。 -
どちらの組織もソフトウェア・エンジニアを
ou=Developers
で識別します。
ここでは、両方の組織のエンジニアをRESTful Services
およびSQL Developer
ロールにマッピングする必要があります。
-
最初のルールにより、組織
example.com
のエンジニアが中間のDevelopers
ロールにマッピングされます。 -
2つ目のルールにより、組織
acquired.com
のエンジニアが中間のDevelopers
ロールにマッピングされます。 -
最後のルールにより、中間の
Developers
ロールからRESTful Services
およびSQL Developer
ロールにマッピングされます。
4.7 Oracle REST Data ServicesとOracle WebLogic Serverの統合
Oracle REST Data Services (ORDS)では、複雑なユーザーIDまたはエンタープライズ・ユーザーIDの統合には、Oracle WebLogicサーバーの機能を活用することをお薦めします。Oracle WebLogicサーバーには、既存の企業のアイデンティティ・ソリューションと統合するための有用で多様な機能が用意されています。Oracle REST Data ServicesがWebLogicにデプロイされると、これらの機能を活用してORDSベースのRESTfulサービスへのアクセスを保護できます。
構成後、ORDSはOracle WebLogicサーバーに対して認証済のユーザーIDとロールを提供するように要求し、その後、ORDSはユーザー・ロールのメンバーシップに基づいてORDSベースのRESTfulサービスを保護するためのアクセス権を認可できます。
Oracle WebLogicサーバーと連携するようにORDSを構成するには、次のコマンドを実行して、Oracle WebLogicと統合するためのords.war
を準備します。
java -jar ords.war oam-config
コマンドの使用方法の説明を表示するには、helpに続けてコマンド名を入力します。
java -jar ords.war help oam-config
4.7.1 Oracle WebLogic Serverと統合するためのORDSの構成
Oracle WebLogicサーバーと連携するようにORDSを構成するには、次のコマンドを実行して、Oracle WebLogicサーバーと統合するためのords.war
ファイルを準備します。
java -jar ords.war oam-config
次のコマンドを実行して、oam-config
コマンドのヘルプを表示します。
java -jar ords.war help oam-config
oam-configコマンドの機能
oam-config
コマンドは、ords.war
ファイル内のweb.xml
デプロイメント・ディスクリプタを再構成して、設定されたユーザーIDをORDSに渡すようにWebLogicに指示します。前述のコマンドを実行した後、ords.war
ファイルをWebLogicサーバーに再デプロイする必要があります。
ORDSによるユーザーのIDとロールの決定方法
ORDSは、Oracle WebLogicサーバーから提供されるAPIを使用して、設定されたユーザーIDからWLSUserおよびWLSGroupを取得します。
ORDSでは、WLSGroupは、ユーザーが所有するロールと同等であるとみなされます。たとえば、ユーザーが「Sales Assistant」という名前のWLSGroupに属している場合、ORDSではそのユーザーはSales Assistantという名前のロールを持つとみなされます。
WebLogicサーバーが認証ユーザーを確立する方法
ユーザーはログイン・フォームでシングル・サインオンにアクセスし、IDとロールを示すCookieまたはアクセス・トークンを取得します。Cookieまたはトークンは、次にOracle WebLogicサーバーに渡されます。Oracle WebLogicサーバーは、Cookieまたはトークンを検証し、それを特定のユーザーにマップし、ユーザーが所有するロールを決定するように構成されています。これは、WebLogicサーバーがリクエストをORDSに渡す前に行われます。ORDSがリクエストを受け取ると、Oracle WebLogicサーバーで提供されているAPIをコールしてWLSUserとWLSGroupを取得し、WebLogicサーバーからユーザーIDとロールの情報を取得します。
4.8 Oracle REST Data Services PL/SQL APIの使用
Oracle REST Data Servicesには、多くの操作でSQL Developerのグラフィカル・インタフェースのかわりに使用できるPL/SQL API (アプリケーション・プログラミング・インタフェース)があります。使用可能なサブプログラムは次のPL/SQLパッケージに含まれています。
-
Oracle REST Data Services: Oracle REST Data Services PL/SQLパッケージのリファレンスを参照
-
OAUTH: 「OAUTH PL/SQLパッケージのリファレンス」を参照
Oracle REST Data Services PL/SQL APIを使用するには、まず次の手順を実行する必要があります。
-
RESTfulサービスを開発するために使用するデータベースに、Oracle REST Data Servicesをインストールします。
-
RESTアクセス用に1つ以上のデータベース・スキーマを有効化します。
トピック:
4.8.1 PL/SQL APIを使用したRESTfulサービスの作成
REST対応スキーマに接続してORDS.CREATE_SERVICEプロシージャを使用することで、RESTfulサービスを作成できます。
次の例では、簡単な「Hello-World」タイプのサービスを作成します。
begin ords.create_service( p_module_name => 'examples.routes' , p_base_path => '/examples/routes/', p_pattern => 'greeting/:name', p_source => 'select ''Hello '' || :name || '' from '' || nvl(:whom,sys_context(''USERENV'',''CURRENT_USER'')) "greeting" from dual'); commit; end; /
この例では、次の手順が実行されます。
-
examples.routesという名前のリソース・モジュールを作成します。
-
モジュールのベース・パス(URI接頭辞としても知られている)を
/examples/routes/
に設定します。 -
モジュールに、ルート・パターンが
greeting/:name
のリソース・テンプレートを作成します。 -
GETハンドラを作成し、そのソースを短い挨拶を作成するSQL問合せとして次の手順で設定します。
-
GET
はp_method
パラメータのデフォルト値で、そのパラメータが省略されているため、ここではそのデフォルト値が使用されます。 -
COLLECTION_FEED
はp_method
パラメータのデフォルト値で、そのパラメータが省略されているため、ここではそのデフォルト値が使用されます
-
-
whom
という名前のオプションのパラメータが指定されます。
関連トピック
4.8.2 RESTfulサービスのテスト
作成したRESTfulサービスをテストするために、まだ開始されていなければOracle REST Data Servicesを開始します。
java -jar ords.war
ブラウザでサービスのURIを入力します。次の例ではwhom
パラメータが指定されていないため、デフォルトでは現行ユーザーからJoe
に対して「Hello」の挨拶を表示します。
http://localhost:8080/ords/ordstest/examples/routes/greeting/Joe
この例の説明は、次のとおりです。
-
Oracle REST Data Servicesは、localhostで実行されていて、ポート8080でリスニングしています。
-
Oracle REST Data Servicesは、コンテキスト・パス
/ords
でデプロイされています。 -
RESTfulサービスは、
ordstest
と呼ばれるデータベース・スキーマで作成されました。 -
URLにはオプションのwhomパラメータが含まれていないため、:whomバインド・パラメータはnull値にバインドされ、その結果、問合せは現行データベース・ユーザー(
sys_context(''USERENV'',''CURRENT_USER'')
)の値をかわりに使用することになります。
ブラウザにJSON表示拡張機能がある場合、次のような結果が表示されます。
{
"items": [
{
"greeting": "Hello Joe from ORDSTEST"
}
],
"hasMore": false,
"limit": 25,
"offset": 0,
"count": 1,
"links": [
{
"rel": "self",
"href": "http://localhost:8080/ords/ordstest/examples/routes/greeting/"
},
{
"rel": "describedby",
"href": "http://localhost:8080/ords/ordstest/metadata-catalog/examples/routes/greeting/"
},
{
"rel": "first",
"href": "http://localhost:8080/ords/ordstest/examples/routes/greeting/Joe"
}
]
}
次の例は、前述の例と類似していますが、オプションのパラメータwhom
が指定されていて、挨拶がJane
からであることを示しています。
http://localhost:8080/ords/ordstest/examples/routes/greeting/Joe?whom=Jane
今回は、次のような結果になります。
{
"items": [
{
"greeting": "Hello Joe from Jane"
}
],
"hasMore": false,
"limit": 25,
"offset": 0,
"count": 1,
"links": [
{
"rel": "self",
"href": "http://localhost:8080/ords/ordstest/examples/routes/greeting/"
},
{
"rel": "describedby",
"href": "http://localhost:8080/ords/ordstest/metadata-catalog/examples/routes/greeting/"
},
{
"rel": "first",
"href": "http://localhost:8080/ords/ordstest/examples/routes/greeting/Joe"
}
]
}
この結果では、:whom
バインド・パラメータがJane
値にバインドされているため、"from"の後にはORDSTEST
ではなくJane
が続くことに注意してください。
4.9 Oracle REST Data Servicesデータベース認証
この項では、データベース認証機能を使用して、PL/SQLゲートウェイ・コールの基本認証を提供する方法について説明します。
データベース認証機能は、mod-plsqlによって提供される動的なBasic認証と似ています。この認証では、PL/SQLストアド・プロシージャへのアクセスを認証および認可するためにデータベース資格証明が要求されます。
4.9.1 サンプル・データベース・スクリプトのインストール
この項では、サンプル・データベース・スクリプトのインストール方法について説明します。
db_auth $ cd sql/
sql $ sql sys as sysdba
SQLcl: Release Release 18.1.1 Production on Fri Mar 23 14:03:18 2018
Copyright (c) 1982, 2018, Oracle. All rights reserved.
Password? (**********?) ******
Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production
SQL> @install <chosen-password>
注意:
-
SQLcl接続文字列とユーザー資格証明を環境にあわせて調整する必要があります。このデモ・シナリオの場合、SQLclはサービス名
orcl
を使用してデータベースに接続します -
<chosen-password>
は、EXAMPLE_USER1
およびEXAMPLE_USER2
データベース・ユーザーに割り当てたパスワードです。後で参照するために、このパスワード値をメモしておいてください。
-
SAMPLE_PLSQL_APP: 保護された
SAMPLE_PROC
がインストールされるデータベース・スキーマ。 -
EXAMPLE_USER1:
SAMPLE_PLSQL_APP.SAMPLE_PROC
プロシージャに対して実行権限を付与されたデータベース・ユーザー。 -
EXAMPLE_USER2:
SAMPLE_PLSQL_APP.SAMPLE_PROC
プロシージャに対する実行権限を付与された2番目のデータベース・ユーザー。
4.9.2 データベース認証の有効化
この項では、データベース認証機能を有効にする方法について説明します。
データベース認証機能を有効にするには、次のいずれかを実行します。
-
Oracle REST Data Servicesの新規インストールの場合、
/u01/ords/params/ords_params
プロパティ・ファイルの次のエントリを更新します。jdbc.auth.enabled=true
-
既存のOracle REST Data Servicesインストールの場合は、次のコマンドを実行します。
cd /u01/ords $JAVA_HOME/bin/java -jar ords.war set-property jdbc.auth.enabled true
この設定は、PL/SQLゲートウェイ・プール(たとえば、apex.xml
)に適用され、ORDS_PUBLIC_USER
プールなどの他のプール・タイプ(たとえば、apex_pu.xml
)には適用されません。
注意:
jdbc.auth.enabled
設定は、データベース・プールごとに構成できます。または、すべてのプールに対して有効になるようにdefaults.xml
ファイルで構成できます。
例4-11 すべてのプールの有効化設定
jdbc.auth.enabled
設定を有効にする方法を示されています。ords $ java -jar ords.war set-property jdbc.auth.enabled true
Mar 23, 2018 2:23:49 PM oracle.dbtools.rt.config.setup.SetProperty execute
INFO: Modified: /tmp/cd/ords/defaults.xml, setting: jdbc.auth.enabled = true
構成設定を更新したら、Oracle REST Data Servicesを再起動して変更を反映します。
4.9.3 リクエスト検証ファンクションの構成
この項では、リクエスト検証ファンクションを一時的に無効にする方法について説明します。
PL/SQLゲートウェイを介してデータベース内のストアド・プロシージャのホワイトリスト・セットのみを起動する場合は、リクエスト検証ファンクションを使用するようにOracle REST Data Servicesを構成する必要があります(特にOracle Application Expressを使用している場合)。
データベース認証機能のテストに使用するデモ・サンプル・プロシージャはホワイトリストになっていないため、リクエスト検証ファンクションを一時的に無効にする必要があります。
リクエスト検証ファンクションを無効にするには、次のステップを実行します。
-
Oracle REST Data Servicesの構成ファイルが保存されているフォルダを検索します。
-
defaults.xml
ファイルを開きます。 -
security.requestValidationFunction
エントリを探し、ファイルから削除します。 -
ファイルを保存します。
-
すでに実行中なら、Oracle REST Data Servicesを再起動します。
注意:
本番環境では、アプリケーション用にアクセスするストアド・プロシージャをホワイトリストに入れるカスタム・リクエスト検証ファンクションを使用する必要があります4.9.4 データベース認証済ユーザーのテスト
この項では、データベース・ユーザーが認証されているかどうかをテストする方法について説明します。
Oracle REST Data Serviceがローカル・ホストおよびポート8080でスタンドアロン・モードで実行されている場合は、Webブラウザで次のURLにアクセスします。
http://localhost:8080/ords/sample_plsql_app.sample_proc
ブラウザにより、資格証明の入力が求められます。ユーザー名にexample_user1
を入力し、サンプル・スキーマのインストール時に書き留めたパスワード値を入力します。
ブラウザには「Hello EXAMPLE_USER1!」が表示され、データベース・ユーザーが認証済で、ユーザーの識別情報がREMOTE_USER
という名前のOWA CGI変数を介してデータベースに伝播されたことを示します。
4.9.5 サンプル・データベース・スキーマのアンインストール
データベース・スキーマをアンインストールするには、次のコード・スニペットに示すようにコマンドを実行します。
db_auth $ cd sql/
sql $ sql sys as sysdba
SQLcl: Release Release 18.1.1 Production on Fri Mar 23 14:03:18 2018
Copyright (c) 1982, 2018, Oracle. All rights reserved.
Password? (**********?) ******
Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production
SQL> @uninstall
4.10 事前フック・ファンクションの概要
この項では、Oracle REST Data Services (ORDS)ベースのRESTコールの前に呼び出されるPL/SQLベースの事前フック・ファンクションの使用方法について説明します。
通常、事前フック・ファンクションはアプリケーションのすべてのRESTエンドポイントに適用する必要があるアプリケーション・ロジックを実装するために使用されます。たとえば、事前フックでは次の機能を使用できます。
- アプリケーション固有のデータベース・セッション状態の構成: VPDポリシーをサポートするようにセッションを構成します。
- カスタム認証および認可: RESTサービスをディスパッチする前に事前フックが呼び出されると、リクエスト・ヘッダーの検査、リクエストを実行するユーザーの判別、およびそのユーザーにリクエストを行う権限があるかどうかの確認を行うために使用されます。
- 監査またはメトリックの収集: 呼び出されたREST APIに関する情報をトラッキングします。
4.10.1 事前フック・ファンクションの構成
この項では、事前フック・ファンクションを構成する方法について説明します。
事前フック・ファンクションは、procedure.rest.preHook
設定を使用して構成します。この設定の値は、ストアドPL/SQLファンクションの名前である必要があります。
4.10.2 事前フック・ファンクションの使用
この項では、事前フック・ファンクションの使用方法について説明します。
事前フックは、引数のないPL/SQLファンクションである必要があり、BOOLEAN
値を戻す必要があります。ファンクションは、リクエストがマップされるデータベース・ユーザーが実行できる必要があります。たとえば、ORDS対応のスキーマにリクエストがマップされている場合、そのスキーマ(またはPUBLIC
)には事前フック・ファンクションに対する実行権限が付与されている必要があります。
ファンクションがtrue
を返した場合、リクエストの通常の処理を続行する必要があることを示します。ファンクションがfalse
を返した場合は、リクエストのさらなる処理を中止する必要があることを示します。
ORDSは、PL/SQLゲートウェイ・ツールキット環境であるOWA (Oracle Web Agent)で事前フック・ファンクションを呼び出します。つまり、ファンクションはリクエスト・ヘッダーおよびOWA CGI環境変数をイントロスペクトし、その情報を使用してそのロジックを実行できます。ファンクションでは、OWA PL/SQL APIを使用してリクエストに対するレスポンスを生成することもできます(たとえば、事前フック・ファンクションでリクエストのさらなる処理を中止し、独自のレスポンスを提供する必要がある場合など)。
4.10.3 リクエストの処理
事前フック・ファンクションは、リクエストの処理を続行する必要があると判断した場合、true
を返す必要があります。そのような場合、事前フック・ファンクションによって生成されるOWAレスポンスは無視され(ユーザーのIDアサーションで説明されているケースを除く)、RESTサービスは通常どおりに呼び出されます。
4.10.4 ユーザーのIDアサーション
この項では、事前フック・ファンクションでユーザーのIDのアサーションを行う方法について説明します。
処理を続行する場合、事前フックはリクエストを行っているユーザーに割り当てられているIDおよびロールに関するアサーションを行うことができます。この情報はRESTサービスの処理で使用されます。事前フック・ファンクションは、次のOWAレスポンス・ヘッダーのいずれかまたは両方を設定することによってこれを判断できます。
X-ORDS-HOOK-USER
: リクエストを実行するユーザーを識別します。この値は、:current_user
暗黙的パラメータおよびREMOTE_IDENT
OWA CGI環境変数にバインドされます。X-ORDS-HOOK-ROLES
: ユーザーに割り当てられているロールを識別します。この情報は、RESTサービスにアクセスするユーザーの認可を判断するために使用されます。このヘッダーが存在する場合は、X-ORDS-HOOK-USER
も存在する必要があります。
注意:
X-ORDS-HOOK-USER
ヘッダーおよびX-ORDS-HOOK-ROLES
ヘッダーは、RESTサービスのレスポンスに含まれません。これらのヘッダーは、ORDSによって内部でのみ使用され、ユーザーのIDおよびロールを伝播します。
これらのレスポンス・ヘッダーを使用すると、事前フックをORDSのロール・ベースのアクセス制御モデルと統合できます。これにより、アプリケーション開発者はサード・パーティの認証およびアクセス制御システムと有用な統合を構築できます。
4.10.5 リクエストの処理の中止
この項では、事前フック・ファンクションでリクエストの処理を中止する方法について説明します。
事前フックがRESTサービスの処理を続行しないと判断した場合、ファンクションはfalse
値を返す必要があります。この値は、リクエストのさらなる処理を試行できないことをORDSに示します。
事前フックがOWA出力を生成しない場合、ORDSは403 Forbidden
のエラー・レスポンス・ページを生成します。事前フックがOWAレスポンスを生成する場合、ORDSはレスポンスとしてOWA出力を返します。これにより、RESTサービスの処理が中止されたときにクライアントが受け取るレスポンスを事前フック・ファンクションでカスタマイズできます。
4.10.6 事前フックが実行可能であることの確認
スキーマが事前フック・ファンクションを呼び出すことができない場合、ORDSはそのスキーマに対するすべてのリクエストに対して503 Service Unavailable
のレスポンスを生成します。事前フックが構成されているため、ORDSでは事前フック・ファンクションを呼び出さずにリクエストの処理を続行することは安全ではありません。ORDS対応のすべてのスキーマで事前フック・ファンクションが実行可能であることが重要です。事前フック・ファンクションが実行可能でない場合、それらのスキーマで定義されたRESTサービスは使用できません。
4.10.7 事前フック・ファンクションによる例外処理
たとえば、実行時エラーが発生して、事前フックがエラー状態と判断した場合、NO DATA FOUND
例外が発生します。このような場合、セキュアではないため、ORDSはRESTサービスの処理を続行できません。ORDSは、事前フック・ファンクションで発生した例外をリクエストが禁止されていることのシグナルとして解釈し、403 Forbidden
のレスポンスを生成して、RESTサービスの呼出しに進みません。このため、事前フックで予期しない例外が発生した場合、そのRESTサービスへのアクセスが禁止されます。予期しないエラー状態が適切に処理され、RESTサービスが使用できない状態にならないように、すべての事前フック・ファンクションが堅牢な例外処理ブロックを必ず持つようにすることをお薦めします。
4.10.8 事前フック・ファンクションの効率性
事前フック・ファンクションは、RESTサービス・コールごとに呼び出されます。このため、事前フック・ファンクションは効率的になるように設計する必要があります。事前フック・ファンクションが非効率の場合は、RESTサービス・コールのパフォーマンスに悪影響を及ぼすことになります。事前フックの呼出しでは、少なくとも1つの追加のデータベース・ラウンドトリップが必要となります。ラウンドトリップのレイテンシ・オーバーヘッドが最小化されるように、ORDSインスタンスとデータベースを近くに配置することが重要です。
4.10.9 事前フックの例
この項では、事前フック・ファンクションを活用できる様々な方法を示すサンプルのPL/SQLファンクションを示します。
次の項に示す例のソース・コードは、解凍したOracle REST Data Servicesディストリビューション・アーカイブのexamples/pre_hook/sql
サブフォルダに含まれています。
4.10.9.1 例のインストール
この項では、事前フックの例のインストール方法について説明します。
examples/pre_hook/sql/install.sql
スクリプトを実行します。次のコード・スニペットは、Oracle SQLclコマンドライン・インタフェースを使用して例をインストールする方法を示しています。pre_hook $ cd examples/pre_hook/sql/
sql $ sql sys as sysdba
SQLcl: Release Release 18.1.1 Production on Fri Mar 23 14:03:18 2018
Copyright (c) 1982, 2018, Oracle. All rights reserved.
Password? (**********?) ******
Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production
SQL> @install <chosen-password>
- SQLcl接続文字列とユーザー資格証明を環境にあわせて調整する必要があります。これらのデモ・シナリオの場合、SQLclはサービス名
orcl
を使用してデータベースに接続します。 <chosen-password>
は、PRE_HOOK_TEST
データベース・ユーザーに割り当てたパスワードです。後で参照するために、このパスワード値をメモしておいてください。examples/pre_hook/sql/install.sql
コマンドは、次の2つのデータベース・スキーマを作成します。- ユーザーIDが格納される
custom_auth_users
という名前のデータベース表とともに事前フック・ファンクションが定義されるPRE_HOOK_DEFNS
スキーマ。この表には、単一のユーザーjoe.bloggs@example.com
が移入されます。そのパスワードは<chosen-password>
に割り当てられた値です。 - 事前フックの例で使用されるORDSベースのRESTサービスが定義された
PRE_HOOK_TESTS
スキーマ。
- ユーザーIDが格納される
4.10.9.1.1 例: すべてのアクセスの拒否
最も単純な事前フックは、RESTサービスへのアクセスをすべて拒否するものです。
false
を返す必要があります。create or replace function deny_all_hook return boolean as
begin
return false;
end;
/
grant execute on deny_all_hook to public;
説明:
deny_all_hook
事前フック・ファンクションは、常にfalse
値を返します。- 実行権限はすべてのユーザーに付与されます。そのため、ORDS対応のスキーマがこのファンクションを呼び出すことができます
ORDSの構成
deny_all_hook
事前フック・ファンクションを有効にするには、次のステップを実行します。
- Oracle REST Data Servicesの構成ファイルが保存されているフォルダを検索します。
defaults.xml
ファイルを開いて、次のエントリを追加します。<entry key="procedure.rest.preHook">pre_hook_defns.deny_all_hook</entry>
- ファイルを保存します。
- Oracle REST Data Servicesを再起動します。
例の実行
インストール・スクリプトによって、ORDS対応のスキーマ、および次のURLでアクセスできるRESTサービスが作成されます(ORDSがlocalhost
にデプロイされ、ポート8080
をリスニングしていることを想定)。
http://localhost:8080/ords/pre_hook_tests/prehooks/user
ブラウザでこのURLにアクセスします。次のようなレスポンスを受け取ります。
403 Forbidden
これは、deny_all_hook
事前フック・ファンクションが呼び出され、false
値が返されてRESTサービスにアクセスできないことを示しています。
4.10.9.1.2 例: すべてのアクセスの許可
deny_all_hook
事前フック・ファンクションのソース・コードを変更して、すべてのRESTサービス・リクエストへのアクセスを許可します。create or replace function deny_all_hook return boolean as
begin
return true;
end;
/
例の実行
ブラウザで次のテストURLにアクセスします。
http://localhost:8080/ords/pre_hook_tests/prehooks/user
{
"authenticated_user": "no user authenticated"
}
注意:
事前フック・ファンクションが認可したため、RESTサービスが実行されます。関連トピック
4.10.9.1.3 例: ユーザーIDのアサーション
次のコード・スニペットは、事前フック・ファンクションがユーザーIDおよびそれらが所有するロールに関するアサーションをどのように行うかを示しています。
create or replace function identity_hook return boolean as
begin
if custom_auth_api.authenticate_owa then
custom_auth_api.assert_identity;
return true;
end if;
custom_auth_api.prompt_for_basic_credentials('Test Custom Realm');
return false;
end;
事前フックは、ユーザーを認証するタスクをcustom_auth_api.authenticate_owa
ファンクションに委任します。ユーザーが認証されていることをこのファンクションが示す場合、custom_auth_api.assert_identity
プロシージャが呼び出され、ユーザーIDおよびロールがORDSに伝播されます。
ORDSの構成
- Oracle REST Data Servicesの構成ファイルが保存されているフォルダを検索します。
defaults.xml
ファイルを開いて、次のエントリを追加します。<entry key="procedure.rest.preHook">pre_hook_defns.identity_hook</entry></entry>
- ファイルを保存します。
- Oracle REST Data Servicesを再起動します。
例の実行
インストール・スクリプトによって、ORDS対応のスキーマおよび次のURLでアクセスできるRESTサービスが作成されます(ORDSがlocalhostにデプロイされ、ポート8080をリスニングしていることを想定)。
http://localhost:8080/ords/pre_hook_tests/prehooks/user
注意:
このURLに初めてアクセスすると、ブラウザに資格証明の入力を求めるプロンプトが表示されます。ユーザー名にjoe.bloggs@example.com
と入力し、インストール・スクリプトの実行時に<chosen-password>
に割り当てた値をパスワードに使用します。リンクをクリックしてサインインします。
{"authenticated_user":"joe.bloggs@example.com"}
4.10.9.2 例のアンインストール
この項では、例をアンインストールする方法について説明します。
次のコード・スニペットは、例をアンインストールする方法を示しています。
pre_hook $ cd sql/
sql $ sql sys as sysdba
SQLcl: Release Release 18.1.1 Production on Fri Mar 23 14:03:18 2018
Copyright (c) 1982, 2018, Oracle. All rights reserved.
Password? (**********?) ******
Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production
SQL> @uninstall
4.11 ハイパーリンクの生成
Oracle REST Data Services (ORDS)では、リレーショナル結果セットをJSON表現に変換するメカニズムが提供され、結果セットのページ間の移動を可能にするために結果セットを自動的にページ分割するハイパーリンクが提供されます。
多くのユースケースでは、結果セットの特定の列をハイパーリンクとして処理する必要があります。ORDSでは、RESTリソースにハイパーリンクを追加するための、次の簡単で強力なメカニズムが提供されています。
-
主キー・ハイパーリンク: 予約された別名
$.id
を持つ列は、結果セット内の単一行の主キー列を示します。このような列値は、結果セット内のその特定の行に関する詳細を提供する現在のリソースの子リソースを指すハイパーリンクの形成に使用されます。 -
任意のハイパーリンク: 別名が予約文字
$
で始まる列は、ハイパーリンクとして扱われます。列別名の後続の文字は、リンク関係タイプを示します。
4.11.1 主キー・ハイパーリンク
この項では、主キー・ハイパーリンクを追加する方法について説明します。
通常、REST APIをモデル化する場合は、他のリソースへのハイパーリンクを列挙するリソース・コレクション・パターンをモデル化する必要があります。
EMP
表を使用する場合、次のコード・スニペットに示すようにサービスを定義できます。begin
ords.define_service(
p_module_name => 'links.example',
p_base_path => 'emp-collection/',
p_pattern => '.',
p_source => 'select empno "$.id", empno id, ename employee_name from emp order by empno ename';
commit;
end;
- 予約値'
.
'は、p_pattern
値に使用されます。これは、この例のリソース・モジュールemp-collection/
のベース・パスにあるリソース・テンプレートのパスを示します。 EMPNO
列には$.id
の別名が付けられ、ハイパーリンクが生成されます。
{
"items": [{
"id": 7369,
"employee_name": "SMITH",
"links": [{
"rel": "self",
"href": "http://localhost:8080/ords/ordstest/emp-collection/7369"
}]
},
...
],
"hasMore": false,
"limit": 25,
"offset": 0,
"count": 14,
"links": [{
"rel": "self",
"href": "http://localhost:8080/ords/ordstest/emp-collection/"
}, {
"rel": "describedby",
"href": "http://localhost:8080/ords/ordstest/metadata-catalog/emp-collection/"
}, {
"rel": "first",
"href": "http://localhost:8080/ords/ordstest/emp-collection/"
}]
}
EMPNO
列の値とサービスのURLが連結され、関係self
を含む新しいハイパーリンクが生成されることを確認します。値は単に連結されず、RFC3986で指定されたアルゴリズムを使用して解決されます。そのため、Oracle REST Data Services (ORDS)は列の値を取得し、解決アルゴリズムを適用して新しい絶対URLを生成できます。
関連項目:
rfc3986の第5項begin
ords.define_template(
p_module_name => 'links.example',
p_pattern => ':id');
ords.define_handler(
p_module_name => 'links.example',
p_pattern => ':id',
p_source_type => ords.source_type_collection_item,
p_source => 'select emp.empno "$.id", emp.* from emp where empno = :id');
commit;
end;
4.11.2 任意のハイパーリンク
この項では、階層内で1レベル上のリソースを指すハイパーリンクを作成する方法について説明します。
$
文字で始まる列はすべて、ハイパーリンクとして扱われます。次のコード・スニペットの例は、従業員リソースがマネージャにハイパーリンクを提供する方法を示しています。begin
ords.define_handler(
p_module_name => 'links.example',
p_pattern => ':id',
p_source_type => ords.source_type_collection_item,
p_source => 'select emp.empno "$.id", emp.*, emp.mgr "$related" from emp where empno = :id');commit;end;
ORDSでは、$related
という列がハイパーリンクとして扱われ、列値はリソースの包含するベースURIを基準とした相対パスとして扱われます。RFC 3986で指定されているアルゴリズムを適用することで、$.id
列値が絶対URIに変換される方法と同様です。
関連項目:
rfc3986の第5.2項。{
"empno": 7369,
"ename": "SMITH",
"job": "CLERK",
"mgr": 7902,
"hiredate": "1980-12-17T00:00:00Z",
"sal": 800,
"comm": null,
"deptno": 20,
"links": [{
"rel": "self",
"href": "http://localhost:8080/ords/ordstest/emp-collection/7369"
}, {
"rel": "describedby",
"href": "http://localhost:8080/ords/ordstest/metadata-catalog/emp-collection/item"
}, {
"rel": "collection",
"href": "http://localhost:8080/ords/ordstest/emp-collection/"
}, {
"rel": "related",
"href": "http://localhost:8080/ords/ordstest/emp-collection/7902"
}]
}
related
リンクは、従業員のマネージャ・リソースを指すことに注意してください。同様に、マネージャ・リソースには、会社の社長でありmgr
列がnull
の従業員番号7839に達するまで、管理チェーンの上にあるマネージャなどを指す関連リンクがあります。列値がnullの場合、ORDSはハイパーリンクを作成しません。{
"empno": 7839,
"ename": "KING",
"job": "PRESIDENT",
"mgr": null,
"hiredate": "1981-11-17T00:00:00Z",
"sal": 5000,
"comm": null,
"deptno": 10,
"links": [{
"rel": "self",
"href": "http://localhost:8080/ords/ordstest/emp-collection/7839"
}, {
"rel": "describedby",
"href": "http://localhost:8080/ords/ordstest/metadata-catalog/emp-collection/item"
}, {
"rel": "collection",
"href": "http://localhost:8080/ords/ordstest/emp-collection/"
}]
}
4.11.2.1 関連するリンク関係について
この項では、拡張リンク関係タイプではなく既存の登録済リンク関係タイプを使用することについて説明します。
RFC 8288第2.1.2項に従って、拡張リンク関係は単純な値ではなくURIである必要があります。つまり、manager
などのリンク関係は、仕様に従った有効なリンク関係ではないということです。カスタム・リンク関係タイプの場合、相互運用性が低下します。アプリケーションで、未登録のリンク関係タイプを使用する場合、カスタム・リンク関係タイプを理解できるのは少数のクライアントのみになります。逆に、登録済リンク関係タイプを使用すると、リンク関係に移動できるクライアントが多くなります。拡張リンク関係タイプではなく既存の登録済リンク関係タイプを使用することをお薦めします。
関連トピック
4.11.2.2 URL解決
この項では、ORDSがURI解決アルゴリズムを使用して列値を解決する方法について説明します。
関連トピック
4.11.2.2.1 子パス
この項では、相対パスを使用して子リソースを参照する方法について説明します。
select'child/resource'"$related" from dual
https://example.com/ords/some_schema_alias/some/resource
であると仮定すると、リンクは次のコード・スニペットに示すようになります。{
"rel": "related",
"href": "https://example.com/ords/some_schema_alias/some/child/resource"
}
4.11.2.2.2 祖先パス
この項では、ORDSで../
および./
構文を使用して、現在のリソースの親パスを参照する方法を示す例を示します。
select'../'"$up", './'"$self" from dual
https://example.com/ords/some_schema_alias/some/collection/
であるとすると、リンクは次のコード・スニペットに示すようになります。
{
"rel": "up",
"href": "https://example.com/ords/some_schema_alias/some/"
},
{
"rel": "self",
"href": "https://example.com/ords/some_schema_alias/some/collection/"
}
4.11.2.2.3 絶対URL
この項では、絶対パスの例を示します。
select'/cool/stuff'"$related", 'https://oracle.com/rest'"$related" from dual
https://example.com/ords/some_schema_alias/some/collection/
であるとすると、リンクは次のコード・スニペットに示すようになります。
{
"rel": "related",
"href": "https://example.com/cool/stuff"
},
{
"rel": "related",
"href": "https://oracle.com/rest"
}
同じリンク関係に対して複数のリンクを作成できます。
4.11.2.2.4 コンテキスト・ルートの相対パス
この項では、コンテキスト・ルートの相対パスの例を示します。
コンテキスト・ルートの相対パスは、ORDS対応スキーマのルート・リソースのURLです。
次のコード・スニペットは、前の項で説明した例のコンテキスト・ルート・パスを示しています。
https://example.com/ords/some_schema_alias/
select'^/another/collection/'"$related"from dual
https://example.com/ords/some_schema_alias/some/collection/
であるとすると、リンクは次のコード・スニペットに示すようになります。
{
"rel": "related",
"href": "https://example.com/ords/some_schema_alias/another/collection"
}
^/1
で始まるパスはすべて、コンテキスト・ルート・パスを基準として解決されます。
4.11.2.2.5 動的パス
この項では、ハイパーリンクに動的な値を設定する方法について説明します。
emp-collection
または:id
リソースに対して、GETハンドラを再定義できます。begin
ords.define_handler(
p_module_name => 'links.example',
p_pattern => ':id',
p_source_type => ords.source_type_collection_item,
p_source => 'select emp.empno "$.id", emp.*, decode(emp.mgr, null, null, '^/managers/' || emp.mgr) "$related" from emp where empno = :id');
commit;
end;
-
$related
列の値は、emp.mgr
の値がnull
でないかぎり、^/managers/:
emp.mgr
から形成されます。このような場合は、ORDSがハイパーリンクを生成しなくなるnull
値が置換されます。
次のコード・スニペットは、更新済の従業員リソースを示しています。
{
"empno": 7566,
"ename": "JONES",
"job": "MANAGER",
"mgr": 7839,
"hiredate": "1981-04-01T23:00:00Z",
"sal": 2975,
"comm": null,
"deptno": 20,
"links": [{
"rel": "self",
"href": "http://localhost:8080/ords/ordstest/emp-collection/7566"
}, {
"rel": "describedby",
"href": "http://localhost:8080/ords/ordstest/metadata-catalog/emp-collection/item"
}, {
"rel": "collection",
"href": "http://localhost:8080/ords/ordstest/emp-collection/"
}, {
"rel": "related",
"href": "http://localhost:8080/ords/ordstest/managers/7839"
}]
}
注意:
related
リンクは、動的に生成されたパス、つまりmanagers/:id
リソースを指すようになりました。