2 Oracle REST Data Servicesアプリケーションの開発
関連項目:
すぐに開始する場合は、『Oracle REST Data Servicesクイック・スタート・ガイド』のチュートリアルを試すことができます。
ノート:
- この章で説明する例を試す前に、Oracle APEX 4.2以降とOracle REST Data Services 3.0以降の両方をインストールして構成していることを確認します。
- JSONデータ永続性用のOracle REST APIを使用する前に、Oracle REST APIをインストールします。『Oracle REST Data Services SODA for REST開発者ガイド』を参照してください
- Oracle APEXを初めて使用する場合は、Oracle APEXのドキュメントを参照してください。
トピック:
2.1 関連するソフトウェアの紹介
この項では、Oracle REST Data Servicesを使用するアプリケーションを開発するための、いくつかの重要な関連ソフトウェアについて説明します。
トピック:
2.1.1 Oracle APEX
ORDSを使用すると、PL/SQLゲートウェイ機能を介してAPEXアプリケーションをWebLogic ServerやTomcatなどの様々なアプリケーション・サーバーで使用できるようになります。これは、Oracle Databaseのすべてのエディションで使用可能な、完全にサポートされている無料のオプションです。Webブラウザのみを使用して、高速でセキュアなプロフェッショナル・アプリケーションを開発し、デプロイできます。
2.1.2 REST API
Representational State Transfer (REST)は、World Wide Webのような分散ハイパーメディア・システムのためのソフトウェア・アーキテクチャのスタイルです。APIは、RESTの原則に適合する場合にRESTfulと称されます。RESTの詳しい説明はこのマニュアルの対象外ですが、REST APIの特性を次に示します。
-
データは一連のリソースとしてモデル化されます。リソースはURIで識別されます。
-
リソースの操作には、小さく統一的な操作セットが使用されます(たとえば、PUT、POST、GET、DELETE)。
-
リソースは、複数の形式で表示できます(たとえば、ブログはHTML形式およびRSS形式で表示できます)。
-
サービスはステートレスですが、クライアントが関連リソースへのアクセスを望む可能性があるため、戻される表現の中で(通常はハイパーテキスト・リンクを提供することで)関連リソースを示します。
ORDSには組込みWebアプリケーションのSQL Developer Webがあり、REST APIの構築、テスト、ドキュメント化および保護に使用されます。
2.2 RESTfulサービスのスタート・ガイド
この項では、RESTfulサービスを紹介し、RESTfulサービスを使用するアプリケーションを開発するためのガイドラインと例を提供します。
トピック:
2.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(リソースの削除)という、リソースで実行可能な標準メソッドが定義されます。
関連トピック
2.2.2 ORDS RESTful Webサービスのアーキテクチャ図
この項では、ORDS RESTful Webサービスのアーキテクチャ図について説明します。
次の図は、ORDS RESTful Webサービス・アーキテクチャの様々なコンポーネント間の関係を示しています。
データベース・スキーマは、REST対応のスキーマです。複数のリソース・モジュールを含めることができます。同様に、ORDSが提供するRESTサービスのトップレベル・コンテナであるリソース・モジュールには、複数のリソース・テンプレートを含めることができます。リソース・テンプレートは、URLの末尾部分で表されます。それぞれのリソース・テンプレートに、4つのリソース・ハンドラ(GET、POST、PUTおよびDELETE)を含めることができます。
https://<HOSTNAME:PORT>/<CONTEXT>/<DATABASE_SCHEMA_ALIAS>/<MODULE_BASE_URI>/<TEMPLATE_URI>/-
HOSTNAME:PORT/CONTEXT: ORDSが実行されているアドレスを指定します。ORDSベースURIとも呼ばれます。 -
DATABASE_SCHEMA_ALIAS: RESTでデータベース・スキーマを有効化する際に指定した名前を指定します。デフォルトでは、小文字のスキーマの名前です。 -
MODULE_BASE_URI: モジュールのURIを指定します。 -
TEMPLATE_URI: テンプレートのURIを指定します。この値は、MODULE_BASE_URIとともにORDSエンドポイントURLを構成します。
次の図は、GET操作の実行方法を示しています。
https://localhost:8080/ords/hr/api/employees/2.2.3 リクエスト・パスの構文要件について
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に適用され、パーセント・エンコーディングによる回避の試みを阻止します。
2.2.4 インストールに含まれるドキュメント「スタート・ガイド」
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でのみ使用可能です。)
2.2.5 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ヘッダーを表示するように指示します。
2.3 RESTアクセスのためのスキーマ・オブジェクトの自動的な有効化(AutoREST)
表、ビューまたはPL/SQLファンクション、プロシージャまたはパッケージへのRESTアクセスを有効化すると、RESTfulサービスを介したアクセスが可能になります。
AutoRESTは、データベース表をRESTリソースとして公開する素早く簡単な方法です。AutoREST機能を使用すると、柔軟性とカスタマイズのしやすさが失われますが、時間と労力を大幅に削減できます。AutoRestによってデータを素早く公開できますが、(例えた言い方をすると)ガイド・レールのセットに乗せてしまいます。たとえば、出力形式や入力形式をカスタマイズできず、追加の検証も実行できません。
一方、手動で作成したリソース・モジュールでは、RESTリソースをサポートするためにSQLおよびPL/SQLを指定する必要があります。リソース・モジュールを使用することは労力を要しますが、柔軟性を向上します。たとえば、どのフィールドを含めるかのカスタマイズ、複数の表の結合、およびPL/SQLを使用した受信データの検証を実現できます。
そのため、アプリケーション開発者は、AutoRESTの「ガイド・レール」を使用するか、まさに必要なことを実行するためにリソース・モジュールを作成するかを選択する必要があります。AutoRESTを選択した場合、スキーマ内で表(または表のセット)を有効にするだけです。
スキーマを有効化することは、スキーマ内のすべての表とビューを有効化することとは異なることに注意してください。Oracle REST Data Servicesにスキーマが存在することを認識させ、HTTPに公開するリソースがゼロまたはそれ以上ある可能性があることを意味するのみです。それらのリソースは、AutoRESTリソースでも、リソース・モジュール・リソースでもかまいません。
ノート:
この機能は、Oracle REST Data Services対応スキーマでのみ使用でき、Oracle APEXワークスペースでは使用できません。関連項目:
ORDS.ENABLE_OBJECT1つ以上の指定した表、ビューまたはPL/SQLプログラムに対するOracle REST Data Servicesアクセスを有効にするには、SQL Developerで次を実行します。
-
RESTアクセス用にスキーマ(接続に関連付けられているスキーマ)を有効にします。
スキーマ・レベル: 接続に関連付けられているスキーマの選択されたオブジェクト(次のステップで指定)へのOracle REST Data Servicesアクセスを有効化するには、「接続」ナビゲータでその名前を右クリックし、「RESTサービス」、「RESTサービスの有効化」の順に選択します。スキーマを有効にしたら、Webインタフェースを介して、そのスキーマまたはユーザーを使用してスキーマ内のSQL Developer WebおよびREST有効オブジェクトにログインできます。
(接続に関連付けられているスキーマのオブジェクトへのOracle REST Data Servicesアクセスのサポートを削除するには、「接続」ナビゲータでその名前を右クリックし、「RESTサービス」、「RESTサービスの削除」の順に選択します。)
-
希望するオブジェクトのRESTアクセスを個別に有効化します。
表またはビュー・レベル: 指定した表またはビューへのOracle REST Data Servicesアクセスを有効化するには、「接続」ナビゲータでその名前を右クリックし、「RESTサービスの有効化」の順に選択します。
- スキーマ別名: REST APIのURIでスキーマの別名を設定できます。これにより、APIコンシューマはデータベース・ユーザー・アカウントを認識できなくなります。
- 承認が必要: スキーマのAPIカタログ・エンドポイントを保護します。このオプションを有効にすると、スキーマのmetadata-catalogエンドポイントへのリクエストに承認が必要になります。
使用方法の詳細は、SQL Developerのウィザードまたはダイアログ・ボックスの「ヘルプ」ボタンをクリックします。
2.3.1 例: RESTfulサービスを使用してオブジェクトにアクセスする
この項では、Oracle REST Data Services問合せの使用例およびREST対応した後の表やビューに対するその他の操作の例を示します。
SQL Developerを使用して、表オブジェクトおよびビュー・オブジェクトを自動的にRESTfulサービスとして公開できます。この項では、これらのRESTfulサービスにアクセスする例を説明します。
ヒント:
こうした例は、これらのリソースにアクセスするのに使用するURLパターンを示しますが、クライアントはこれらのURLの構造の知識をハード・コーディングしないでください。かわりに、クライアントはリソースのハイパーリンクに従ってリソース間を移動してください。URLパターンの構造は、将来のリリースで進化したり、変更されたりする可能性があります。
この項では、RESTfulサービスを使用してオブジェクトにアクセスする例を説明します。
2.3.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のあるリンクはリソースを説明します。
2.3.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/"
}
]
}2.3.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/"
}
]
}2.3.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"
}
]
}2.3.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"
}
]
}2.3.1.6 主キーを使用した表の行のGet
この例では、オブジェクトを識別するキーの値を指定することでオブジェクトを取得します。
ノート:
- 表に主キーがない場合、ORDSはROWIDを使用して行を一意にアドレス指定します。
- 次のいずれかの特性を満たす主キーは、RESTインタフェースと互換性がありません。
- ピリオドで終わる
- //または\\を含む
- /で始まる
- 2つ以上のピリオドを連続して含む(例: ..、...)
- 次のいずれかの文字を含む: 「<」、「>」、「:」、「"」、「|」、「?」、「*」、「#」、「;」または「%」
このような主キーを含むリクエストは、レスポンスとしてHTTP 400 Bad Requestを返します。主キーに前述の互換性のない文字が含まれている場合は、リンク生成ルールと競合しない2次キーを使用することをお薦めします。
パターン: 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/"
}
]
}2.3.1.7 表の行の挿入
この例では、オブジェクトにデータを挿入します。リクエストに付加するボディのデータは、挿入するデータを格納したJSONオブジェクトです。
オブジェクトに主キーがある場合、POSTリクエストで本文に主キーの値を含めることができます。または、表にIDENTITY CLAUSE、順序またはトリガーがある場合は、主キー列を省略できます。表に主キーがない場合には、行の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/"
}
]
}2.3.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/"
}
]
}2.3.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
}2.3.1.10 バッチ・ロードによるPost
この例では、バッチ・ロード機能を使用してオブジェクトのデータを挿入します。リクエストに付加するボディのデータはCSVファイルです。バッチ操作の動作はオプションの問合せパラメータを使用して制御できます。このパラメータは表2-1で説明しています。
パターン: POST http://<HOST>:<PORT>/ords/<SchemaAlias>/<ObjectAlias>/batchload?<Parameters>
パラメータ:
表2-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
2.3.2 問合せでのフィルタリング
この項では、REST対応の表やビューに対する問合せでのフィルタリングの例を示し、説明します。
フィルタリングは、全コレクションで見つかった項目のサブセットが含まれている複数ページのリソース全体に対し、リクエストごとの動的フィルタ定義を使用してコレクション・リソースを制限する処理です。フィルタリングは、大規模なコレクションの効率的な走査を可能にします。
問合せでフィルタリングするには、q=FilterObjectパラメータを含め、FilterObjectはリソースに適用するカスタムな選択やソートを表すJSONオブジェクトです。たとえば、次のようなリソースを仮定します。
https://example.com/ords/scott/emp/
次の問合せには、ENAME列を「JOHN」に制限するフィルタが含まれています。
https://example.com/ords/scott/emp/?q={"ENAME":"JOHN"}
2.3.2.1 FilterObjectの構文
FilterObjectは、次の構文に準拠したJSONオブジェクトである必要があります。
FilterObject { orderby , asof, wmembers }
orderby、asofおよびwmembers属性はオプションで、その定義は次のとおりです。
orderby
"$orderby": {orderByMembers}
orderByMembers
orderByProperty
orderByProperty , orderByMembers
orderByProperty
columnName : sortingValue
columnName : sortingNulls
columnName : sortingValues
sortingValues
[sortingValue]
[sortingNulls]
[sortingValue, sortingNulls]
[sortingNulls, sortingValue]
sortingNulls
"NULLS FIRST"
"NULLS LAST"
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項に従って符号化する必要があります。
2.3.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} } Order by with nulls first { "$orderby": {"SALARY": ["ASC", "NULLS FIRST"]} } Order by with nulls last { "$orderby": {"SALARY": ["ASC", "NULLS LAST"]} } 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%"}} ] } }
2.3.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パッケージ・オブジェクトの範囲内で名前を付けられているオブジェクトなので、個々に有効化することはできません。このため、粒度レベルがパッケージ・レベルでオブジェクトを有効化します。この粒度レベルは、そのパブリック・ファンクションおよびプロシージャをすべて公開可能にします。
ノート:
オーバーロードしたパッケージ・ファンクションとプロシージャはサポートされていません。2.3.3.1 PL/SQLオブジェクトの自動有効化がサポートされているメソッドとコンテンツ・タイプ
この項では、この機能によってサポートされるメソッドおよびコンテンツ・タイプについて説明します。
ノート:
この機能はRPCスタイルのインタラクションを行うため、CRUDからHTTPメソッドへの標準データ・マッピングには適用できません。サポートされるコンテンツ・タイプは、application/jsonです。
2.3.3.2 PL/SQLオブジェクトの自動有効化
この項では、Oracle REST Data Servicesを介してPL/SQLオブジェクトを自動的に有効化する方法を説明します。
2.3.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;
/例2-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;
/例2-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;
/2.3.3.2.2 SQL Developerを使用したPL/SQLオブジェクトの自動有効化
この項では、SQL Developer 4.2以降を使用してPL/SQLオブジェクトを有効化する方法を説明します。
SQL Developerを使用してPL/SQLオブジェクト(たとえば、パッケージ)を有効化するには、次のステップを実行します。
ノート:
これでパッケージ、ファンクションおよびプロシージャを有効化できるようになりました。ただし、有効化の粒度は、パッケージ全体レベル、スタンドアロン・ファンクション・レベル、またはスタンドアロン・プロシージャ・レベルのいずれかです。-
SQL Developerで、次の図に示すようにパッケージを右クリックします。
-
「RESTfulサービスを有効にする」を選択して、次のウィザード・ページを表示します。
-
オブジェクトの有効化: このオプションを有効にします(つまり、パッケージのRESTアクセスを有効にします)。
-
オブジェクト別名: オブジェクト別名として
registry_pkgを受け入れます。 -
承認が必要: 簡潔性を保つため、このオプションは無効にしておきます。
-
ウィザードのRESTfulサマリー・ページで「終了」をクリックします。
-
2.3.3.3 PL/SQLエンドポイントの生成
HTTPエンドポイントは、有効なデータベース・オブジェクトに対してリクエストに応じて動的に生成されます。Oracle REST Data Servicesは、問合せを使用してエンドポイントを生成するために、接続したデータベース・カタログを使用します。
HTTPエンドポイントを生成するため、すべてのデータベース・オブジェクトに対して次のルールが適用されます。
-
名前はすべて小文字に変換されます
-
エンドポイントがすでに割り当てられていなければ、生成されます
ストアド・プロシージャおよびストアド・ファンクションのエンドポイント
ファンクションまたはプロシージャ名は、同じネームスペースの表やビューと同じ方法でURL内に生成されます。
例2-3 ストアド・プロシージャのためのエンドポイントの生成
CREATE OR REPLACE PROCEDURE MY_SCHEMA.MY_PROC IS
BEGIN
NULL;
END;http://localhost:8080/ords/my_schema/my_proc/例2-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のエンドポイントは、オーバーロードしているため生成されません。
2.3.3.4 リソース入力ペイロード
入力ペイロードは、REST標準に従った値を持つJSONドキュメントです。
ペイロードは、次のコード・スニペットに示すように、INまたはIN OUTの各パラメータに対する名前/値ペアを含んでいる必要があります。
{
"p1": "abc",
"p2": 123,
"p3": null
}ノート:
INまたはIN OUTパラメータがない場合、次のコード・スニペットに示すように、空のJSONボディが必要です。{
}2.3.4 JSONリレーショナル二面性ビューのサポート
ORDSは、JSONリレーショナル二面性ビュー機能を有効にするAutoRESTをサポートしています。この機能はOracle Database 23c以降でのみサポートされます。
JSONリレーショナル二面性ビューは、リレーショナル・データベースとNoSQL JSONドキュメント・ストアの利点を組み合せた革新的なOracle Database機能です。この機能により、正規化されたデータをJSONでアプリケーションに公開しながらリレーショナル表に格納できます。同じリレーショナル・データに複数のJSONリレーショナル二面性ビューを作成して、様々なユースケースに対応できます。つまり、同じリレーショナル・データに異なるJSON表現を含めることができます。
関連項目:
JSONリレーショナル二面性開発者ガイド2.3.4.1 表AutoRESTとJSONリレーショナル二面性ビューAutoRESTの比較
JSONリレーショナル二面性ビューは、Oracle DatabaseではVIEWとして分類されるため、リレーショナル・ビューと同様にAutoRest対応にできます。この項では、JSONリレーショナル二面性ビューとリレーショナル表のAutoREST機能を比較します。
- エンドポイントおよびメソッドの同じセット(
GET、PUT、POST、DELETEおよびHEAD)を公開します。 - 関連付けられたルート表と同じカンマ区切りの主キー識別子書式を使用します。
- 同じ
Read、Create、UpsertまたはDeleteセマンティクスをサポートします。 - 複数のアイテムが処理される同じHTTP
If-None-MatchヘッダーETagダイジェストを生成します。 - レスポンス・ペイロードにリンク・ハイパーリンク・フィールドを挿入します
- Oracle Database 23c以降でのみサポートされます
- JSONペイロードを、リクエストまたはレスポンスとJSONリレーショナル二面性ビューのDATA列の間で直接渡します。
- 単一アイテムが処理される(
GET、PUTおよびDELETEメソッド)、HTTPIf-MatchおよびIf-None-Matchヘッダー条件付き一致に、JSONリレーショナル二面性ビューのETag値を使用します。 - SODA拡張された例による問合せ(QBE)構文を使用して、豊富なフィルタリングと順序付けを行います
- JSON対応の
batchload形式を使用します
2.3.4.2 拡張されたETag一致のサポート
Oracle REST Data Services (ORDS)は、コミット時のロックおよびクライアント・キャッシングをサポートするために、JSONリレーショナル二面性ビューのETag機能と統合されています。
HTTP ETag一致
ORDSは、GET (If-None-Match)やPUT/DELETE (If-Match)などの単一アイテム操作の一致ヘッダーを評価するときに、独自のダイジェスト値ではなく、JSONリレーショナル二面性ビューの生成されたETagを使用します。
Matchヘッダー
|
HTTP Falseレスポンス
|
ヘッダーの例 |
|---|---|---|
If-None-Match |
304 – "Not Modified" |
If-None-Match: "536001F31A8718819AEEF28EC20D8677" |
If-Match |
412 – "Precondition Failed" |
If-Match: "536001F31A8718819AEEF28EC20D8677" |
ノート:
ETag値を囲む二重引用符は必須です。
データベースETag一致
Oracle Databaseでは、リクエスト・ペイロードの_metadataオブジェクトでETagが使用可能なUPDATE操作に対してもETag一致が実行されます。それ以外の場合、このフィールドは他のすべてのケースで無視されます。
| コンテンツの例 | HTTP 'False'レスポンス |
|---|---|
|
412 – "Precondition Failed" |
2.3.4.3 拡張されたJSON QBE (例による問合せ)フィルタリング
Oracle REST Data Services (ORDS)は、Simple Oracle Document Access (SODA)で使用されるのと同じQBEフィルタリング構文を公開し、JSONを処理するためにより適切なJSON演算子および機能の堅牢なセットをユーザーに提供します。
現在、構文はJSONリレーショナル二面性ビューにのみ適用されますが、リレーショナル表およびビューと同様に、q URLパラメータで指定されます。
次の例では、race_dv JSONリレーショナル二面性ビュー(pointsフィールドが40より大きい)のコンテンツをフィルタリングします。
curl http://localhost:8080/ords/janus/race_dv/?q={"points":{"$gt":40}}次の例では、pointsフィールドの順序を前の例に追加します。
curl http://localhost:8080/ords/janus/race_dv/?q={"$query":{"points":{"$gt":40}},"$orderby":[{"path":"points","datatype":"number"}]}
2.3.4.4 拡張されたJSONバッチ・ロード
DATA列はリクエスト・ペイロードに直接マップされるため、同じアプローチをバッチ・ロードに適用する必要があります。したがって、ORDSは、次のJSONコンテンツ・タイプのいずれかを受け入れる最適化されたbatchloadエンドポイントを提供します。
| ヘッダーContent-Type | 説明 |
|---|---|
application/json |
JSONドキュメント・ペイロードの自由形式のJSON配列。たとえば:
|
application/json; boundary=LF |
JSONドキュメントの改行区切りリスト。ペイロードの例:
|
各JSONドキュメントは、ORDSバッチ・ロード・サービスに行として渡され、任意の表と同じ方法で問合せパラメータを使用して微調整できます。
たとえば、batchesPerCommit、batchRowsおよびtruncateを使用して、バッチ・ロード・プロセスを最適化できます。
次の例は、JSONドキュメントの25行のバッチでのpoints_dv JSONリレーショナル二面性ビューのバッチ・ロードを示しています。
curl -i -X POST --data-binary @points.json -H "Content-Type: application/json"
http://localhost:8080/ords/ordstest/points_dv/batchload?batchRows=25HTTP/1.1 200 OK
...
#INFO Number of rows processed: 2
#INFO Number of rows in error: 0
#INFO Last row processed in final committed batch: 2
SUCCESS: Processed without errors
2.4 SQLおよびPL/SQLを使用したRESTful Servicesの手動作成
この項では、SQLおよびPL/SQLを使用して手動でRESTful Servicesを作成する方法を説明し、JSONドキュメントを使用してRESTリクエストのボディにあるストアド・プロシージャにパラメータを渡す方法を表示します。
2.4.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つのステップを、パラメータ引き渡しタスクを実行する前に完了する必要があります(次以降のサブセクションを参照)。
関連トピック
2.4.1.1 JSONを使用したパラメータの引き渡し
この項では、RESTリクエスト(たとえばPOSTまたはPUTメソッド)のボディでJSONドキュメントを使用してストアド・プロシージャにパラメータを渡す方法を示します(各パラメータは名前/値ペア)。この操作はレコード上で更新を実行し、その結果、レコードに対する変更がOUTパラメータとして戻されます。
次のステップを実行します。
ノート:
-
すべてのパラメータはオプションです。 JSONドキュメントでパラメータの名前/値ペアを省略すると、パラメータは
NULLに設定されます。 -
名前/値ペアは、JSONドキュメント内に、任意の順序で並べることができます。 JSONを使用すると、JSONドキュメントでこの点に多くの柔軟性を得られます。
-
1レベルのJSONのみサポートされます。JSONオブジェクトまたは配列をネストすることはできません。
2.4.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のルート・パターン」を参照してください。
2.4.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」を入力します(次の図を参照)。
図2-12 問合せ文字列を使用してGETメソッドとともにいくつかのパラメータ名/値ペアを送信した結果をブラウザを使用して表示する

「図2-12 問合せ文字列を使用してGETメソッドとともにいくつかのパラメータ名/値ペアを送信した結果をブラウザを使用して表示する」の説明
この問合せは、名前がTurner、部門が30、給与が1500、管理者が7698であるセールスマンに対応する1件のレコードを戻します。
-
パラメータ値をURLエンコードするのは有効です。必ずしも必要ではないこともありますが、行っても安全です。これにより、インターネットにより何かが改変されること、たとえば、特殊文字が障害を引き起こす可能性がある他の文字に変換されることを防げます。RESTクライアントにこの機能があることもありますし、フレーズ
urlエンコーダでインターネットを検索することでその機能があるツールを見つけることもできます。 -
URIでパラメータ・リストの末尾に決してバックスラッシュを入れないでください。そうしないと、
404 Not Foundエラーが表示される場合があります。
2.4.2 SQL/JSONデータベース・ファンクションの使用
この項では、Oracle Database 19cリリース以降で利用できるSQL/JSONデータベース・ファンクションを使用して、ネストされたJSONオブジェクトと階層関係表を互いにマップするために説明します。
この項には次のトピックが含まれます:
2.4.2.1 ネストされたJSONオブジェクトの関係表への挿入
この項では、ネスト配列を持つJSONオブジェクトを複数の階層的な関係表に挿入する方法を説明します。
この機能を実装するために使用される2つの主要なテクノロジは次のとおりです。
-
Oracle REST Data Servicesが提供してPOSTおよび他のRESTコールのボディにあるJSONおよび他のコンテンツをPL/SQL RESTハンドラに配信する
:bodyバインド変数 -
Oracle Database 21cで提供されるJSON_TABLEおよびその他のSQL/JSON演算子
関係表にデータを挿入するためのこれらのテクノロジを使用する利点のいくつかを次に示します。
-
機能を実装するための要件が最小限です。たとえば、JSONパーサー・ソフトウェアのインストールは不要です
-
JSONからの関係マッピングが単純な場合、書くのも読むのも簡単な、単純な宣言型コードを使用できます
-
より複雑なマッピングを処理する機能は強力で洗練されています。次のものが含まれます。
-
NULLSおよびブール値をマッピングするためのメカニズム
-
JSONを処理するための洗練されたメカニズム。JSONは時間とともに進化します。このため、マッピング・コードは、JSONドキュメントの古いバージョンも新しいバージョンも処理できる必要があります。
たとえば、単純なスカラー値が進化して、複数のスカラーまたはネストされたスカラー値やオブジェクトの配列を含むJSONオブジェクトになる場合があります。スカラー値を戻すSQL/JSON演算子は、単純なスカラーがこれらのより精巧な構造内に埋め込まれた場合でも、引き続き機能できます。特別なメカニズム(Ordinality列と呼ばれます)を使用して、値が導出されたところから構造を決定することができます。
-
2.4.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_textバインド変数はCLOBデータ型であり、CLOB変数にのみ割り当てることができます。:bodyまたは:body_textを使用する場合は、ORDS:bind変数を介して個々のJSON属性を参照できません。
関連項目:
Database SQL言語リファレンス2.4.2.1.2 ネストされたLineItemsがあるJSON発注書の例
この項では、ネストされたLineItemsがあるJSON発注書を取得し、PurchaseOrder表の行およびLineItem表の行に挿入する例を示します。
例2-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}]}'2.4.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));
2.4.2.1.4 POSTリクエストのPL/SQLハンドラ・コード
この項では、POSTリクエストに対応するサンプルのPL/SQLハンドラ・コードを示します。ハンドラ・コードは、PurchaseOrder表の行およびLineItem表の行に発注書を挿入するために使用されます。
例2-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;2.4.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サービスを定義します。
2.4.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;2.4.2.2 階層リレーショナル・データからのネストされたJSONオブジェクトの生成
この項では、Oracle REST Data Servicesを使用して、階層(親/子)関係内の関係表を問い合わせ、ネストされたJSON形式でデータを戻す方法を説明します。
この機能を実装するために使用される2つの主要なテクノロジは次のとおりです。
-
Oracle Databaseでは、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の値にマッピングできます。
2.4.2.2.1 リレーショナル・データのJSON生成のバイパス
この項では、すでにJSON形式のレスポンスを処理するためのソリューションについて説明し、提供します。
ORDSは、SQLまたはPL/SQLの結果とレスポンスをアプリケーションに戻す前にJSON形式に自動フォーマットします。ただし、場合によっては、レスポンス本文全体またはその一部がすでにJSON形式になっていることがあります。このような2つのユースケースを次に示します。
ユースケース1: レスポンスがすでにJSON形式の場合
Select 'application/json',
upper(json_doc)
from json_playこの場合、メディア・リソースはapplication/jsonであり、ブラウザではBLOBまたはPDFと同様に処理されます。
ユースケース2: レスポンスの1つ以上の列がすでにJSON形式になっている。
1つ以上の列がJSON形式の場合、属性をJSON形式に変換する必要がないことを示すために、ソース問合せのこのような列に別名を付ける必要があります。
Select id,
jsons "{}jsons"
from table_with_json別名テキストは、ネストされたJSONドキュメント属性の名前を指定するために使用されます。
2.4.2.2.2 階層関係表からのネストされたJSONオブジェクトの生成例
この項では、ネストされたJSON発注書の形式でPurchaseOrderおよびLineItem関係表に挿入したデータを問い合わせるか、GETする方法を説明します。
例2-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 = :id2.4.2.2.3 テンプレートとGETハンドラを定義するためのPL/SQL APIコール
この項では、作成したモジュールに新しいテンプレートを作成するためのOracle REST Data Services PL/SQL APIコールの例を提供します。
例2-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; 2.4.2.3 RESTfulサービスのテスト
この項では、Oracleデータベースにアクセスして結果をJSON形式で取得するためにPOSTおよびGET RESTful Servicesをテストする方法を示します。
この項には次のトピックが含まれます:
2.4.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: chunked2.5 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は日付データ型をサポートします。この項には次のトピックが含まれます:
2.5.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文でセッション・タイムゾーンを変更できます。
関連項目:
インターネット日時書式2.5.2 タイムゾーンの設定について
Oracle REST Data Servicesの起動時に、それにより内部で実行されるJVMは、Oracle REST Data Servicesが様々なタイムゾーン変換に使用するタイムゾーンを取得およびキャッシュします。デフォルトでは、ORDSをスタンドアロンで実行する場合、タイムゾーンはUTCに設定されます。これは、ords serveコマンドを実行する前に環境変数JVM_TIMEZONEを設定することでオーバーライドできます。言うまでもなく、タイムゾーンを変更するための指示は、オペレーティング・システムにより異なります。
もしなんらかの理由でOSと同じタイムゾーンを使用したくない場合、Java環境変数Duser.timezoneを使用してデフォルトをオーバーライドすることができます。その変数が正確にはどのように設定されているかは、スタンドアロン・モードとJavaアプリケーション・サーバーのどちらで実行されているかにより異なります。次のトピックではいくつか例を示します。
スタンドアロン・モード
Oracle REST Data Servicesをスタンドアロン・モードで実行する場合、-jarオプションの前のコマンドライン・オプションとして指定することで、Java環境変数を設定できます。
例2-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という名前のスクリプトを作成することで環境変数を設定します。
例2-10 Duser.timezone Java環境変数のJavaアプリケーション・サーバーでの設定
次のコード例は、Javaアプリケーション・サーバー — Tomcat 8でタイムゾーンを設定するための、setenv.shスクリプトの内容を示しています。
CATALINA_TIMEZONE="-Duser.timezone=America/New_York"
CATALINA_OPTS="$CATALINA_OPTS $CATALINA_TIMEZONE2.5.3 APEXでのサンプルのRESTfulサービスの調査(チュートリアル)
SQL Developerは最新のOracle REST Data Servicesリリース、つまり3.0.Xをサポートしているため、SQL Developer Webを使用してOracle REST Data Servicesアプリケーションを開発することをお薦めします。APEXには、RESTおよびOracle REST Data Servicesの基本的な概念を習得するのに便利なチュートリアルが用意されています。ただし、チュートリアルは以前のOracle REST Data Servicesリリース(2.0.X)を使用しています。チュートリアルの使用方法について説明している有用なヒントをいくつか次に示します。
APEXインスタンスがサンプルのアプリケーションおよびサンプルのデータベース・オブジェクトを自動的にワークスペースに追加するように構成されている場合、リソース・モジュールのリストにoracle.example.hrという名前のサンプルのリソース・モジュールが表示されます。リソース・モジュールがリストにない場合は、RESTfulサービス・ページの右側にあるサンプル・データのリセットタスクをクリックし、サンプルのリソース・モジュールを作成できます。
2.6 Database Actionsを使用したRESTful Webサービスの作成
RESTful Webサービスは、Database Actionsで使用可能な「モジュール」、「テンプレート」および「ハンドラ」ページを使用して作成できます。
関連項目:
RESTful Webサービスの作成2.7 RESTfulサービスへのセキュアなアクセスの構成
この項では、RESTfulサービスへのセキュアなアクセスの構成方法について説明します。
RESTful APIは、それぞれのリソースが一意のURIを持つ複数のリソースから構成されています。リソースのセットは権限によって保護できます。権限はロールのセットを定義し、認証済のユーザーのうちの少なくとも1人は、権限によって保護されたリソースへのアクセス権を持っている必要があります。
特定の権限によって保護されるリソースを構成するには、権限のマッピングを作成する必要があります。権限のマッピングは、権限が保護するリソースを特定するパターンのセットを定義します。
トピック:
2.7.1 認証
ユーザーは、ファースト・パーティのCookieベースの認証またはサード・パーティのOAuth 2.0ベースの認証を使用して認証できます。
トピック:
2.7.1.1 ファースト・パーティのCookieベースの認証
ファースト・パーティは、RESTful APIの作成者です。ファースト・パーティのアプリケーションは、RESTful APIと同じWebオリジンにデプロイされたWebアプリケーションです。ファースト・パーティのアプリケーションは、Webアプリケーションが使用しているものと同じCookieセッションを使用し、RESTful APIに自身を認証し、権限を付与することが可能です。ファースト・パーティのアプリケーションにはRESTful APIへの完全なアクセス権があります。
2.7.1.2 サード・パーティのOAuth 2.0ベースの認証
サード・パーティは、RESTful APIの作成者以外のパーティです。サード・パーティのアプリケーションは、ファースト・パーティのアプリケーションと同じようには信頼できません。そのため、サード・パーティ製のアプリケーションに対し、選択的に制限付きのRESTful APIへのアクセス権を付与するための仲介手段が必要となります。
OAuth 2.0プロトコルは、RESTful APIへの条件付きおよび制限アクセスを提供するフローを定義します。簡単に言えば、サード・パーティのアプリケーションは、まずファースト・パーティに登録する必要があり、その後、ファースト・パーティ(またはファースト・パーティのRESTfulサービスのエンド・ユーザー)が、そのサード・パーティ・アプリケーションに対する期限の短いアクセス・トークンを発行することで、サード・パーティ・アプリケーションのRESTful APIへの制限付きアクセスを承認します。
2.7.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の所有者が承認する必要があります。
2.7.2 リソースにアクセスするための権限について
リソースにアクセスするための権限は、次のデータで構成されます。
-
名前: 権限の一意の識別子。この値は必須です。
-
ラベル: OAuthを使用してユーザーが権限へのアクセスを承認するように求められるとき、エンド・ユーザーに提示される権限の名前。権限がThree-LeggedのOAuthフローで使用される場合、この値は必須です。
-
説明: 権限の目的の説明。これも、ユーザーが権限へのアクセスを承認するように求められるとき、エンド・ユーザーに提示されます。権限がThree-LeggedのOAuthフローで使用される場合、この値は必須です。
-
ロール: 権限に関連付けられているロール名のセット。認証されたパーティは、権限で保護されたリソースへのアクセスを許可されるために、指定されたロールの少なくとも1つを持っている必要があります。値は必須ですが、空のセットとすることはでき、それはユーザーの認証は必要だが、権限にアクセスするための特定のロールは必要ないことを示します。
Two-LeggedのOAuthフローでは、サード・パーティのアプリケーション(OAuthの用語ではクライアントと呼ばれる)は、必要なロールの少なくとも1つを持つ必要があります。
Three-LeggedのOAuthフローでは、サード・パーティのアプリケーションからのアクセス・リクエストを承認するエンド・ユーザーは、必要なロールの少なくとも1つを持つ必要があります。
2.7.3 リソースにアクセスするためのユーザーおよびロールについて
権限は一連のロールを列挙し、ユーザーはロールを持つことができます。Oracle REST Data Servicesは、ユーザー管理のタスクをOracle REST Data Servicesがデプロイされているアプリケーション・サーバーに委任します。
Oracle REST Data Servicesでは、アプリケーション・サーバーによって定義および管理されるユーザーを認証でき、認証されたユーザーが所属するロールおよびグループを識別できます。アプリケーション・サーバーへのOracle REST Data Servicesのデプロイを担当するユーザーは、アプリケーション・サーバーのユーザー・リポジトリも構成する必要があります。
ユーザー・リポジトリを定義したり、既存のユーザー・リポジトリと統合したり、アプリケーション・サーバーはいろいろな方法で構成できるため、アプリケーション・サーバーのユーザー・リポジトリを構成する方法はこのドキュメントでは説明できません。詳細は、アプリケーション・サーバーのドキュメントを参照してください。
2.7.4 ファイルベースのユーザー・リポジトリについて
Oracle REST Data Servicesでは、簡易なファイルベースのユーザー・リポジトリ・メカニズムが提供されます。ただし、このユーザー・リポジトリはデモおよびテストのみを目的としており、本番使用はサポートされていません。
このリポジトリにユーザーを作成する方法の詳細は、次のように、ユーザー・コマンドのコマンドライン・ヘルプを参照してください。
ords config user --help
形式:
ords config user add <name> <roles>
例:
ords config user add ords_dev "SQL Developer"
引数:
-
<user>はユーザーのユーザーIDです。 -
<roles>はユーザーが持つロールのリストです。リスト内の複数のロールを区切るには、カンマを使用します。
関連トピック
2.7.5 チュートリアル: リソースの保護およびアクセス
このチュートリアルでは、次のOAuth機能を使用し、リソースのセットを保護するための権限を作成し、保護されたリソースにアクセスする方法を示します。
-
クライアント資格証明
-
認可コード
-
暗黙のフロー
また、ファースト・パーティCookieベースの認証を使用してリソースにアクセスする方法を示します。
トピック:
2.7.5.1 OAuthフローと各フローの用途
この項では、様々なOAuthフロー機能の用途を説明します。
ファースト・パーティCookieベースの認証は、RESTful APIと同じオリジンでホストされるWebアプリケーションからRESTful APIにアクセスするときに使用します。
認可コード・フローは、RESTful APIにアクセスするサード・パーティのWebアプリケーションを許可する必要があり、そのサード・パーティ・アプリケーションが、安全にクライアントの資格証明を保持できる独自のWebサーバーを持っている場合に使用します。これは、ほとんどのWebアプリケーションの標準的な状況で、サード・パーティのアプリケーションは、アプリケーションの再認証をユーザーに促すことなく、リフレッシュ・トークンを使用してユーザー・セッションの存続期間を延長でき、最高のセキュリティと最高のユーザー・エクスペリエンスを提供できます。
暗黙のフローは、サード・パーティのアプリケーションがその資格証明を安全に保持できるWebサーバーを持たない場合に使用します。このフローは、サード・パーティの単一ページ・ベースのアプリケーションで役立ちます。暗黙のフローではリフレッシュ・トークンを発行できないので、ユーザーはアプリケーションを認証するように頻繁に促されます。
ネイティブ・モバイルやデスクトップのアプリケーションは、認可コードまたは暗黙のフローを使用する必要があります。それらは、Webブラウザの画面にサイン・インおよび認可のプロンプトを表示し、認可処理の最後にWebブラウザの画面からアクセス・トークンを取得する必要があります。
クライアント資格証明フローは、RESTful APIによって管理されるデータへのアクセスを承認するようにユーザーに要求せず、サード・パーティのアプリケーションにRESTful APIへの直接アクセスを提供する必要がある場合に使用します。このサード・パーティのアプリケーションは、資格証明の機密を保持できるサーバー・ベースのアプリケーションである必要があります。クライアント資格証明はいつでもネイティブの実行可能ファイル内で検出できるため、クライアント資格証明フローはネイティブ・アプリケーションでは使用しないでください。
2.7.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/
2.7.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管理者のロールを持つテスト・ユーザーを作成します。コマンド・プロンプトで次のコマンドを実行します。ords config user add 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"} ] }
2.8 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開発者ガイド』を参照してください。 SQL Administrator- このロールはデータベースAPI用であり、pdbライフサイクル管理操作に必要です。
トピック:
2.8.1 Oracle APEXのユーザーとOracle REST Data Servicesのロールについて
デフォルトでは、Oracle APEXのユーザーはOracle REST Data Servicesの事前定義済ユーザー・ロールを持っていません。これは、デフォルトでは、APEXのユーザーは次のことができないことを意味します。
-
保護されたRESTfulサービスの起動
-
OAuth 2.0アプリケーションの登録
-
Oracle SQL Developerを使用したRESTfulサービスの開発
これは、APEXの開発者および管理者を含め、すべてのAPEXユーザーに適用されます。そこで、APEXのユーザーを適切なユーザー・グループに追加して前述のアクションを実行できるようにするため、次のステップに従うことを覚えておくことが重要です。
トピック:
2.8.1.1 APEXユーザーへのOracle REST Data Servicesロールの付与
APEXユーザーに前述のロールのいずれかを付与するには、ユーザーをロールに対応するAPEXのユーザー・グループに追加する必要があります。たとえば、RESTEASY_ADMINユーザーにRESTful Servicesロールを付与するには、次のステップを実行します。
RESTEASY_ADMINでRESTEASYワークスペースにログインします。- 「管理」に移動し、「ユーザーとグループの管理」に移動します。
RESTEASY_ADMINユーザーの左にある編集アイコンをクリックします。- 「ユーザー・グループ」で、
「RESTfulサービス」を選択します。 - 「変更の適用」をクリックします。
2.8.1.2 APEXユーザーへのOracle REST Data Servicesロールの自動付与
APEXユーザーを適切なユーザー・グループに追加するのは、ステップを見落としがちで、管理するユーザーが多い場合は反復的なタスクとなります。
この問題に対処するため、defaults.xml構成ファイルを変更し、APEXユーザーに自動的に事前定義済の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を再起動する必要があります。
2.8.2 ロールによるRESTfulサービスのアクセス制御
組込みのRESTful Serviceロールは、保護されたRESTfulサービスにアクセスすることを許可されたユーザーの識別に役立つデフォルトです。
しかし、特定のRESTfulサービスにアクセスできるユーザーのセットを制限するため、きめ細かいロール定義が必要になることもあります。
トピック:
2.8.2.1 RESTfulサービスのロールの定義について
RESTfulサービスのロールは、APEXのユーザー・グループです。ギャラリRESTfulサービスへのアクセスを制御するためにユーザー・グループを作成するには、次のステップに従います。 (
-
ワークスペース管理者として
RESTEASYワークスペースにログインします。 -
「管理」に移動し、「ユーザーとグループの管理」に移動します。
-
「グループ」タブをクリックします。
-
「ユーザー・グループの作成」をクリックします。
-
「名前」に
Gallery Usersと入力します。 -
「グループの作成」をクリックします。
2.8.2.2 ロールとRESTful権限の関連付け
ユーザー・グループを作成したら、それをRESTful権限と関連付けることができます。ギャラリ・ユーザーのロールをexample.gallery権限に関連付けるには、次のステップに従います。
- 「SQLワークショップ」に移動し、「RESTfulサービス」に移動します。
- タスクのセクションで、RESTfulサービスの権限をクリックします。
- 「ギャラリ・アクセス」をクリックします。
- 「割当済グループ」で、
ギャラリ・ユーザーを選択します。 - 「変更の適用」をクリックします。
この変更で、ユーザーはギャラリRESTfulサービスにアクセスできるギャラリ・ユーザー・ロールを持ちます。
2.9 WebLogic Serverのユーザー・リポジトリに対する認証
Oracle REST Data Servicesでは、WebLogic Serverによって提供されるAPIを使用し、資格証明(ユーザー名とパスワード)を検証し、ユーザーがメンバーであるグループおよびロールのセットを取得できます。
この項では、WebLogic Serverによって提供される組込みのユーザー・リポジトリでユーザーを作成し、そのユーザーに対して認証を行う機能を検証します。
このドキュメントではWebLogic ServerをLDAPリポジトリなどの多くの一般的なユーザー・リポジトリ・システムと統合する方法は説明しませんが、WebLogic Serverが正しく構成されていれば、Oracle REST Data Servicesでそのようなリポジトリに対して認証が可能です。アプリケーション・サーバーでどのようなユーザー・リポジトリがサポートされているか、およびそれらのリポジトリへのアクセスを構成する方法の詳細は、アプリケーション・サーバーのドキュメントを参照してください。
トピック:
2.9.1 WebLogic Serverに対する認証
WebLogic Serverに対してのユーザー認証には、大きなステップとして次のものがあります。
2.9.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アプリケーションの登録が許可されます。
では、ユーザーを正常に認証できることを検証します。
2.9.1.2 WebLogic Serverユーザーの検証
作成したWebLogic Serverユーザーが正常に認証されることを検証するには、次のステップを実行します。
アプリケーションが1つもリストされていない状態でOAuth 2.0クライアントの登録ページが表示されるはずです。このページが表示された場合は、WebLogic Serverのユーザー・リポジトリに対する認証が機能していることを検証できたことになります。
「ユーザーには、リソースにアクセスする権限がありません。」というメッセージとともにサインオンのプロンプトが再表示される場合は、誤りを犯しています(おそらく、グループ・リストの値のスペルミス)。
2.10 既存のグループ/ロール・モデルとの統合
他の項の例で、WebLogic Serverの組込みのユーザー・リポジトリの構成方法を説明しています。そのような状況では、ユーザー・グループの名前の付け方を完全に制御できます。ユーザーがロールとまったく同じ(大文字/小文字を区別)名前を持つグループのメンバーである場合、そのユーザーはそのロールを持っていると考えられます。
しかし、既存のユーザー・リポジトリと統合する場合は、RESTfulサービスの開発者がユーザー・リポジトリ内のユーザー・グループの命名や編成を制御できないことがあります。このような状況では、ユーザー・リポジトリに定義された既存の「物理」ユーザーグループをOracle REST Data ServicesまたはRESTfulサービス(あるいはその両方)で定義された「論理」ロールにマッピングするメカニズムが必要とされます。
このグループからロールへのマッピングは、Oracle REST Data Servicesではrole-mapping.xmlという名前の構成ファイルを構成することで実現されます。
トピック:
2.10.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ロールの両方を付与します。
トピック:
2.10.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テンプレートに使用するものと同じで、パラメータ名が中カッコ({})で区切られます。
2.10.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という名前の論理ロールにマッピングされます。
2.10.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ロールにマッピングされます。
2.11 Oracle REST Data ServicesとWebLogic Serverの統合
Oracle REST Data Services (ORDS)では、複雑なユーザーIDまたはエンタープライズ・ユーザーIDの統合には、WebLogic Serverの機能を活用することをお薦めします。WebLogic Serverには、既存の企業のアイデンティティ・ソリューションと統合するための有用で多様な機能が用意されています。Oracle REST Data ServicesがWebLogic Serverにデプロイされると、WebLogic Serverの機能を活用してORDSベースのRESTfulサービスにセキュアにアクセスできます。
ORDSがWebLogic Serverと連携するように構成されると、WebLogic Serverは認証済のユーザーIDとロールを提供できます。ORDSは、ユーザー・ロールのメンバーシップに基づいて、保護されたRESTfulサービスへのアクセスを認可します。
2.11.1 WebLogic Serverと統合するためのORDSの構成
この項では、認証のためにWebLogicサーバーと連携するようORDSを構成する方法について説明します。
WebLogicサーバー認証を使用するようにORDSを構成するには、デプロイ可能なORDS.warファイルを生成するときに次のコマンドに示すように--weblogic-authオプションを使用します。
ords war --weblogic-auth <path for new war file>。
ords warコマンドのヘルプを取得するには、--helpオプションを指定します。
ords war --help。
ords warコマンドで--weblogic-authオプションを使用すると、--weblogic-authオプションにより、生成されたWebアプリケーション・ファイル内の web.xmlデプロイメント記述子が再構成され、確立されたユーザーIDをWebLogicサーバーがORDSに渡すのに役立ちます。
ユーザーのIDとロールの決定
前述のコマンドを実行した後、生成されたWebアプリケーション・ファイルをWebLogicサーバーに再デプロイする必要があります。
ORDSは、WebLogic Serverから提供されるAPIを使用して、設定されたユーザーIDからWLSUserおよびWLSGroupを取得します。
ORDSでは、WLSGroupは、ユーザーが所有するロールと同等であるとみなされます。たとえば、ユーザーがSales Assistantという名前のWLSGroupに属している場合、ORDSではそのユーザーはSales Assistantという名前のロールを持つとみなされます。
認証済ユーザー情報の取得
ユーザーはログイン・フォームでシングル・サインオンにアクセスし、IDとロールを示すCookieまたはアクセス・トークンを取得します。Cookieまたはトークンは、次にWebLogic Serverに渡されます。WebLogic Serverは、Cookieまたはトークンを検証し、それを特定のユーザーにマップし、ユーザーが所有するロールを決定するように構成されています。WebLogic Serverは、リクエストをORDSに渡す前にこの操作を実行します。ORDSがリクエストを受け取ると、WebLogic Serverで提供されているAPIをコールしてWLSUserとWLSGroupを取得し、WebLogic ServerからユーザーIDとロールの情報を取得します。
2.12 Oracle REST Data Services PL/SQL APIの使用
Oracle REST Data Servicesには、すべての操作でSQL Developerのグラフィカル・インタフェースのかわりに使用できるPL/SQL API (アプリケーション・プログラミング・インタフェース)があります。使用可能なサブプログラムは次のPL/SQLパッケージに含まれています。
-
ORDS: 「ORDS PL/SQLパッケージのリファレンス」を参照
-
OAUTH: 「OAUTH PL/SQLパッケージのリファレンス」を参照
ノート:
有効化するスキーマまたはORDSパッケージの使用時に公開するORDSサービスに、ユーザーとしてログインする必要があります。ORDSにはパブリックのEXECUTE権限が付与されます。つまり、すべてのユーザーがRESTでスキーマを有効にし、REST APIを公開できます。このパブリックの付与は、対象の環境で望ましくない場合は取り消すことができます。別のスキーマで作業する場合は、ORDS管理者データベース・ロールが必要なORDS_ADMINパッケージを使用します。
-
RESTfulサービスを開発するために使用するデータベースに、Oracle REST Data Servicesをインストールします。
-
RESTアクセス用に1つ以上のデータベース・スキーマを有効化します。
トピック:
2.12.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という名前のオプションのパラメータが指定されます。
関連トピック
2.12.2 RESTfulサービスのテスト
作成したRESTfulサービスをテストするために、まだ開始されていなければOracle REST Data Servicesを開始します。
ords -c \path\to\ords\config serve
ブラウザでサービスの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が続くことに注意してください。
2.13 Oracle REST Data Servicesデータベース認証
この項では、データベース認証機能を使用して、PL/SQLゲートウェイ・コールの基本認証を提供する方法について説明します。
データベース認証機能は、mod-plsqlによって提供される動的なBasic認証と似ています。この認証では、PL/SQLストアド・プロシージャへのアクセスを認証および認可するためにデータベース資格証明が要求されます。
2.13.1 サンプル・データベース・スクリプトのインストール
この項では、サンプル・データベース・スクリプトのインストール方法について説明します。
examples\db_auth $ cd sql/
sql $ sql system/<password>
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番目のデータベース・ユーザー。
2.13.2 データベース認証の有効化
この項では、データベース認証機能を有効にする方法について説明します。
データベース認証機能を有効にするには、次のいずれかを実行します。
-
Oracle REST Data Servicesの新規インストールの場合、
/u01/ords/params/ords_paramsプロパティ・ファイルの次のエントリを更新します。jdbc.auth.enabled=true -
既存のOracle REST Data Servicesインストールの場合、
ords/binが$PATHにあると想定して、次のコマンドを実行します。ords -c c:\ords\config config --db-pool default set jdbc.auth.enabled true出力:
ORDS: Production Release 22.1 on Mon Mar 07 17:01:52 2022 Copyright (c) 2010, 2022, Oracle. All rights reserved. Configuration: /C:/ords/config/ The setting named: jdbc.auth.enabled was set to: true in configuration: default
この設定は、PL/SQLゲートウェイ・プール(たとえば、apex.xml)に適用され、ORDS_PUBLIC_USERプールなどの他のプール・タイプ(たとえば、apex_pu.xml)には適用されません。
ノート:
jdbc.auth.enabled設定は、データベース・プールごとに構成できます。または、すべてのプールに対して有効になるようにdefaults.xmlファイルで構成できます。
例2-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を再起動して変更を反映します。
2.13.3 リクエスト検証ファンクションの構成
この項では、リクエスト検証ファンクションを一時的に無効にする方法について説明します。
PL/SQLゲートウェイを介してデータベース内のストアド・プロシージャのホワイトリスト・セットのみを起動する場合は、リクエスト検証ファンクションを使用するようにOracle REST Data Servicesを構成する必要があります(特にOracle APEXを使用している場合)。
データベース認証機能のテストに使用するデモ・サンプル・プロシージャはホワイトリストになっていないため、リクエスト検証ファンクションを一時的に無効にする必要があります。
リクエスト検証ファンクションを無効にするには、次のステップを実行します。
<Current Configuration directory>/globalディレクトリに移動します。- Oracle REST Data Services構成情報が格納されている
settings.xmlファイルを開きます。 -
security.requestValidationFunctionエントリを探し、ファイルから削除します。 -
ファイルを保存します。
-
すでに実行中なら、Oracle REST Data Servicesを再起動します。
ノート:
本番環境では、アプリケーション用にアクセスするストアド・プロシージャをホワイトリストに入れるカスタム・リクエスト検証ファンクションを使用する必要があります2.13.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変数を介してデータベースに伝播されたことを示します。
2.13.5 サンプル・データベース・スキーマのアンインストール
データベース・スキーマをアンインストールするには、次のコード・スニペットに示すようにコマンドを実行します。
db_auth $ cd sql/
sql $ sql system/<password>
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> @uninstall2.14 事前フック・ファンクションの概要
この項では、Oracle REST Data Services (ORDS)ベースのRESTコールの前に呼び出されるPL/SQLベースの事前フック・ファンクションの使用方法について説明します。
通常、事前フック・ファンクションはアプリケーションのすべてのRESTエンドポイントに適用する必要があるアプリケーション・ロジックを実装するために使用されます。たとえば、事前フックでは次の機能を使用できます。
- アプリケーション固有のデータベース・セッション状態の構成: VPDポリシーをサポートするようにセッションを構成します。
- カスタム認証および認可: RESTサービスをディスパッチする前に事前フックが呼び出されると、リクエスト・ヘッダーの検査、リクエストを実行するユーザーの判別、およびそのユーザーにリクエストを行う権限があるかどうかの確認を行うために使用されます。
- 監査またはメトリックの収集: 呼び出されたREST APIに関する情報をトラッキングします。
2.14.1 事前フック・ファンクションの構成
この項では、事前フック・ファンクションを構成する方法について説明します。
事前フック・ファンクションは、procedure.rest.preHook設定を使用して構成します。この設定の値は、ストアドPL/SQLファンクションの名前である必要があります。
2.14.2 事前フック・ファンクションの使用
この項では、事前フック・ファンクションの使用方法について説明します。
事前フックは、引数のないPL/SQLファンクションである必要があり、BOOLEAN値を戻す必要があります。ファンクションは、リクエストがマップされるデータベース・ユーザーが実行できる必要があります。たとえば、ORDS対応のスキーマにリクエストがマップされている場合、そのスキーマ(またはPUBLIC)には事前フック・ファンクションに対する実行権限が付与されている必要があります。
ファンクションがtrueを返した場合、リクエストの通常の処理を続行する必要があることを示します。ファンクションがfalseを返した場合は、リクエストのさらなる処理を中止する必要があることを示します。
ORDSは、PL/SQLゲートウェイ・ツールキット環境であるOWA (Oracle Web Agent)で事前フック・ファンクションを呼び出します。つまり、ファンクションはリクエスト・ヘッダーおよびOWA CGI環境変数をイントロスペクトし、その情報を使用してそのロジックを実行できます。ファンクションでは、OWA PL/SQL APIを使用してリクエストに対するレスポンスを生成することもできます(たとえば、事前フック・ファンクションでリクエストのさらなる処理を中止し、独自のレスポンスを提供する必要がある場合など)。
2.14.3 リクエストの処理
事前フック・ファンクションは、リクエストの処理を続行する必要があると判断した場合、trueを返す必要があります。そのような場合、事前フック・ファンクションによって生成されるOWAレスポンスは無視され(ユーザーのIDアサーションで説明されているケースを除く)、RESTサービスは通常どおりに呼び出されます。
2.14.4 ユーザーのIDアサーション
この項では、事前フック・ファンクションでユーザーのIDのアサーションを行う方法について説明します。
処理を続行する場合、事前フックはリクエストを行っているユーザーに割り当てられているIDおよびロールに関するアサーションを行うことができます。この情報はRESTサービスの処理で使用されます。事前フック・ファンクションは、次のOWAレスポンス・ヘッダーのいずれかまたは両方を設定することによってこれを判断できます。
X-ORDS-HOOK-USER: リクエストを実行するユーザーを識別します。この値は、:current_user暗黙的パラメータおよびREMOTE_IDENTOWA CGI環境変数にバインドされます。X-ORDS-HOOK-ROLES: ユーザーに割り当てられているロールを識別します。この情報は、RESTサービスにアクセスするユーザーの認可を判断するために使用されます。このヘッダーが存在する場合は、X-ORDS-HOOK-USERも存在する必要があります。
ノート:
X-ORDS-HOOK-USERヘッダーおよびX-ORDS-HOOK-ROLESヘッダーは、RESTサービスのレスポンスに含まれません。これらのヘッダーは、ORDSによって内部でのみ使用され、ユーザーのIDおよびロールを伝播します。
これらのレスポンス・ヘッダーを使用すると、事前フックをORDSのロール・ベースのアクセス制御モデルと統合できます。これにより、アプリケーション開発者はサード・パーティの認証およびアクセス制御システムと有用な統合を構築できます。
2.14.5 リクエストの処理の中止
この項では、事前フック・ファンクションでリクエストの処理を中止する方法について説明します。
事前フックがRESTサービスの処理を続行しないと判断した場合、ファンクションはfalse値を返す必要があります。この値は、リクエストのさらなる処理を試行できないことをORDSに示します。
事前フックがOWA出力を生成しない場合、ORDSは403 Forbiddenのエラー・レスポンス・ページを生成します。事前フックがOWAレスポンスを生成する場合、ORDSはレスポンスとしてOWA出力を返します。これにより、RESTサービスの処理が中止されたときにクライアントが受け取るレスポンスを事前フック・ファンクションでカスタマイズできます。
2.14.6 事前フックが実行可能であることの確認
スキーマが事前フック・ファンクションを呼び出すことができない場合、ORDSはそのスキーマに対するすべてのリクエストに対して503 Service Unavailableのレスポンスを生成します。事前フックが構成されているため、ORDSでは事前フック・ファンクションを呼び出さずにリクエストの処理を続行することは安全ではありません。ORDS対応のすべてのスキーマで事前フック・ファンクションが実行可能であることが重要です。事前フック・ファンクションが実行可能でない場合、それらのスキーマで定義されたRESTサービスは使用できません。
2.14.7 事前フック・ファンクションによる例外処理
たとえば、実行時エラーが発生して、事前フックがエラー状態と判断した場合、NO DATA FOUND例外が発生します。このような場合、セキュアではないため、ORDSはRESTサービスの処理を続行できません。ORDSは、事前フック・ファンクションで発生した例外をリクエストが禁止されていることのシグナルとして解釈し、403 Forbiddenのレスポンスを生成して、RESTサービスの呼出しに進みません。このため、事前フックで予期しない例外が発生した場合、そのRESTサービスへのアクセスが禁止されます。予期しないエラー状態が適切に処理され、RESTサービスが使用できない状態にならないように、すべての事前フック・ファンクションが堅牢な例外処理ブロックを必ず持つようにすることをお薦めします。
2.14.8 事前フック・ファンクションの効率性
事前フック・ファンクションは、RESTサービス・コールごとに呼び出されます。このため、事前フック・ファンクションは効率的になるように設計する必要があります。事前フック・ファンクションが非効率の場合は、RESTサービス・コールのパフォーマンスに悪影響を及ぼすことになります。事前フックの呼出しでは、少なくとも1つの追加のデータベース・ラウンドトリップが必要となります。ラウンドトリップのレイテンシ・オーバーヘッドが最小化されるように、ORDSインスタンスとデータベースを近くに配置することが重要です。
2.14.9 事前フックの例
この項では、事前フック・ファンクションを活用できる様々な方法を示すサンプルのPL/SQLファンクションを示します。
次の項に示す例のソース・コードは、解凍したOracle REST Data Servicesディストリビューション・アーカイブのexamples/pre_hook/sqlサブフォルダに含まれています。
2.14.9.1 例のインストール
この項では、事前フックの例のインストール方法について説明します。
examples/pre_hook/sql/install.sqlスクリプトを実行します。次のコード・スニペットは、Oracle SQLclコマンドライン・インタフェースを使用して例をインストールする方法を示しています。pre_hook $ cd examples/pre_hook/sql/
sql $ sql system/<password>
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が格納される
2.14.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の構成ファイルが保存されているフォルダを検索します。
settings.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サービスにアクセスできないことを示しています。
2.14.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サービスが実行されます。関連トピック
2.14.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の構成ファイルが保存されているフォルダを検索します。
settings.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"}2.14.9.2 例のアンインストール
この項では、例をアンインストールする方法について説明します。
次のコード・スニペットは、例をアンインストールする方法を示しています。
pre_hook $ cd sql/
sql $ sql system/<password>
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
2.15 ハイパーリンクの生成
Oracle REST Data Services (ORDS)では、リレーショナル結果セットをJSON表現に変換するメカニズムが提供され、結果セットのページ間の移動を可能にするために結果セットを自動的にページ分割するハイパーリンクが提供されます。
多くのユースケースでは、結果セットの特定の列をハイパーリンクとして処理する必要があります。ORDSでは、RESTリソースにハイパーリンクを追加するための、次の簡単で強力なメカニズムが提供されています。
-
主キー・ハイパーリンク: 予約された別名
$.idを持つ列は、結果セット内の単一行の主キー列を示します。このような列値は、結果セット内のその特定の行に関する詳細を提供する現在のリソースの子リソースを指すハイパーリンクの形成に使用されます。 -
任意のハイパーリンク: 別名が予約文字
$で始まる列は、ハイパーリンクとして扱われます。列別名の後続の文字は、リンク関係タイプを示します。
2.15.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;
2.15.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/"
}]
}
2.15.2.1 関連するリンク関係について
この項では、拡張リンク関係タイプではなく既存の登録済リンク関係タイプを使用することについて説明します。
RFC 8288第2.1.2項に従って、拡張リンク関係は単純な値ではなくURIである必要があります。つまり、managerなどのリンク関係は、仕様に従った有効なリンク関係ではないということです。カスタム・リンク関係タイプの場合、相互運用性が低下します。アプリケーションで、未登録のリンク関係タイプを使用する場合、カスタム・リンク関係タイプを理解できるのは少数のクライアントのみになります。逆に、登録済リンク関係タイプを使用すると、リンク関係に移動できるクライアントが多くなります。拡張リンク関係タイプではなく既存の登録済リンク関係タイプを使用することをお薦めします。
関連トピック
2.15.2.2 URL解決
この項では、ORDSがURI解決アルゴリズムを使用して列値を解決する方法について説明します。
関連トピック
2.15.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"
}
2.15.2.2.2 祖先パス
この項では、ORDSで../および./構文を使用して、現在のリソースの親パスを参照する方法を示す例を示します。
select'../'"$up", './'"$self" from dualhttps://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/"
}2.15.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"
}
同じリンク関係に対して複数のリンクを作成できます。
2.15.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で始まるパスはすべて、コンテキスト・ルート・パスを基準として解決されます。
2.15.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 リソースを指すようになりました。
2.16 HTTPエラー・レスポンスについて
ORDSは、JSONまたはHTML形式でHTTPエラー・レスポンスを生成できるようになりました。ORDSリリース20.4より前では、HTMLレスポンスのみがサポートされていました。下位互換性を維持するために、デフォルトでは、ORDSはエラー・レスポンスのレンダリングに最適な形式を自動的に決定しようとします。
error.responseFormat設定を構成して、ORDSがエラー・レスポンスを常にHTMLまたはJSON形式でレンダリングするように強制できます。
2.16.1 error.responseFormatについて
error.responseFormat設定は、次の値をサポートするグローバル設定です。
- html - すべてのエラー・レスポンスを強制的にHTML形式にします。
- json - すべてのエラー・レスポンスを強制的にJSON形式にします。
- auto (デフォルト値) - リクエストに最適な形式を自動的に決定します。
2.16.1.1 HTMLモード
error.responseFormat値がhtmlに設定されている場合、すべてのエラー・レスポンスがHTML形式でレンダリングされます。この設定は、ORDS 20.3.1以前のリリースの動作と一致させるために使用できます。HTML形式はWebブラウザで正しく表示されます。ただし、人間以外のクライアントの場合、HTML形式は冗長であり、解析が困難です。
2.16.1.2 jsonモード
error.responseFormat値がjsonに設定されている場合、すべてのエラー・レスポンスがJSON形式でレンダリングされます。JSON形式は、HTTP APIの問題の詳細標準に準拠しています。JSON形式は簡潔で、人間以外のクライアントが簡単に解析できます。ただし、ブラウザには適切に表示されず、技術者以外のユーザーにはわかりづらいです。
2.16.1.3 autoモード
error.responseFormatのデフォルト値はautoです。この値が構成されている場合、ORDSは次のルールを適用して、使用するのに最も適切な形式を自動的に選択します。
- クライアントが
Acceptリクエスト・ヘッダーを提供する場合で、application/jsonまたはapplication/problem+jsonが最も優先されるメディア・タイプの場合、レスポンスはJSON形式である必要があります。 - クライアントが
Acceptリクエスト・ヘッダーを提供する場合でtext/htmlが最も優先されるメディア・タイプの場合、レスポンスはHTML形式である必要があります。 - クライアントが
X-Requested-Withヘッダーを提供する場合、レスポンスはJSON形式である必要があります。このヘッダーが存在することは、リクエストがJavaScriptコードから開始されるため、JSONが適切なレスポンス形式であることを示しています。 - クライアントが
Originヘッダーを提供する場合、レスポンスはJSON形式である必要があります。このヘッダーが存在することは、リクエストがJavaScriptコードから開始されるため、JSONが適切なレスポンス形式であることを示しています。- このルールには例外が1つあり、リクエスト・メソッドが
POSTでリクエストのContent-Typeがapplication/x-www-form-urlencodedの場合、レスポンスはHTML形式になります。
- このルールには例外が1つあり、リクエスト・メソッドが
- クライアントが
curl/で始まる値を持つUser-Agentヘッダーを提供する場合、レスポンスはJSON形式である必要があります。cURLは、HTTPリクエストを行うための一般的なコマンドライン・ツールです。簡潔なJSON形式の方がコマンドライン環境では読みやすくなります。前述のルールのいずれも当てはまらない場合、レスポンスはHTML形式になります。関連項目:
cURL












