注意:
すぐに開始する場合は、ここで「RESTfulサービスのスタート・ガイド」のチュートリアルを試すことができます。ただし、後でこの章に戻り、主要な概念と技術を理解してください。
注意:
チュートリアルおよび例を試してみる前に、Oracle Application Express 4.2以上およびOracle REST Data Services 3.0以上の両方がインストールされ、構成されていることを確認してください。
JSONデータの永続にOracle REST APIを使用する場合は、まずOracle REST APIをインストールする必要があります。詳細は、『Oracle REST Data Services SODA for REST開発者ガイド』のOracle REST APIのインストールに関する項を参照してください。
読者はOracle Application Expressに精通していることを前提としています。Oracle Application Expressを初めて使用する場合は、Oracle Application Expressのドキュメントを参照してください。
トピック:
また、補足的な拡張例として、アプリケーションの構築にOracle Application Expressを使用する「開発チュートリアル: イメージ・ギャラリの作成」を確認することもできます。
この項では、Oracle REST Data Servicesを使用するアプリケーションを開発するための、いくつかの重要な関連ソフトウェアについて説明します。
トピック:
Oracle Application Expressは、Oracleデータベースのための宣言型のラピッドWebアプリケーション開発ツールです。これは、完全にサポートされている、Oracleデータベースのすべてのエディションで利用可能なコスト不要のオプションです。Webブラウザのみを使用して、高速でセキュアなプロフェッショナル・アプリケーションを開発し、デプロイできます。
Representational State Transfer (REST)は、World Wide Webのような分散ハイパーメディア・システムのためのソフトウェア・アーキテクチャのスタイルです。APIは、RESTの原則に適合する場合にRESTfulと称されます。RESTの詳しい説明はこのマニュアルの対象外ですが、RESTful APIの特性を次に示します。
データは一連のリソースとしてモデル化されます。リソースはURIで識別されます。
リソースの操作には、小さく統一的な操作セットが使用されます(たとえば、PUT、POST、GET、DELETE)。
リソースは、複数の形式で表示できます(たとえば、ブログはHTML形式およびRSS形式で表示できます)。
サービスはステートレスですが、クライアントが関連リソースへのアクセスを望む可能性があるため、戻される表現の中で(通常はハイパーテキスト・リンクを提供することで)関連リソースを示します。
Oracle Application Expressのリリース4.2では、Oracle REST Data Servicesの機能を活用し、RESTful Webサービスを定義およびテストするための使いやすいグラフィカル・ユーザー・インタフェースが開発者に提供されています。
この項では、RESTfulサービスを紹介し、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
(リソースの削除)という、リソースで実行可能な標準メソッドが定義されます。
関連トピック
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に適用され、パーセント・エンコーディングによる回避の試みを阻止します。
Oracle REST Data Servicesをインストールすると、参考になるサブフォルダやファイルの入った例のフォルダが作成されます。インストール・フォルダの階層には、次のものがあります。
ords conf docs examples soda getting-started getting-started-nosql ...
階層の内容:
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でのみ使用可能です。)
examples\getting-started-nosql
: index.html
をダブルクリックすると、Oracle REST Data Servicesを使用したNoSQLストア・アクセスを開始する方法についての簡潔なドキュメントが表示されます。
他の項で、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ヘッダーを表示するように指示します。
Oracle REST Data Servicesがデータベース接続に関連付けられたシステムにインストールされている場合、AutoREST機能を使用して、そのデータベース接続と関連付けられたスキーマ内の指定された表およびビューへのOracle REST Data Servicesアクセスを簡単に有効または無効にすることができます。表、ビューまたはPL/SQLファンクション、プロシージャまたはパッケージへのRESTアクセスを有効化すると、RESTfulサービスを介したアクセスが可能になります。
AutoRESTは、データベース表をRESTリソースとして公開する素早く簡単な方法です。労力を削減するために、柔軟性とカスタマイズの容易性を若干犠牲にします。AutoRestによってデータを素早く公開できますが、(例えた言い方をすると)ガイド・レールのセットに乗せてしまいます。たとえば、出力形式や入力形式をカスタマイズできず、追加の検証も実行できません。
一方、手動で作成したリソース・モジュールでは、RESTリソースをサポートするためにSQLおよびPL/SQLを指定する必要があります。リソース・モジュールを使用することは労力を要しますが、柔軟性を向上します。たとえば、どのフィールドを含めるかのカスタマイズ、複数の表の結合、およびPL/SQLを使用した受信データの検証を実現できます。
そのため、アプリケーション開発者は、AutoRESTの「ガイド・レール」を使用するか、まさに必要なことを実行するためにリソース・モジュールを作成するかを選択する必要があります。AutoRESTを選択した場合、スキーマ内で表(または表のセット)を有効にするだけです。
スキーマを有効化することは、スキーマ内のすべての表とビューを有効化することとは異なることに注意してください。Oracle REST Data Servicesにスキーマが存在することを認識させ、HTTPに公開するリソースがゼロまたはそれ以上ある可能性があることを意味するのみです。それらのリソースは、AutoRESTリソースでも、リソース・モジュール・リソースでもかまいません。
Oracle SQL Developerの便利なウィザードを使用して、Oracle REST Data Servicesの問合せによる個々のデータベース・スキーマ・オブジェクト(表、ビュー、およびPL/SQL)へのアクセスを自動的に有効にできます。(これらの機能は、Oracle REST Data Services対応のスキーマでのみ有効で、Oracle Application Expressワークスペースでは有効でないことに注意してください。)
1つ以上の指定した表またはビューに対するOracle REST Data Servicesアクセスを有効にするには、SQL Developerで次を実行する必要があります。
RESTアクセス用にスキーマ(接続に関連付けられているスキーマ)を有効にします。
スキーマ・レベル: 接続に関連付けられているスキーマの(次の手順で指定する)選択したオブジェクトへのOracle REST Data Servicesアクセスを有効にするには、「接続」ナビゲータでその名前を右クリックし、「RESTサービス」、「RESTサービスの有効化」の順に選択します。
(接続に関連付けられているスキーマのオブジェクトへのOracle REST Data Servicesアクセスのサポートを削除するには、「接続」ナビゲータでその名前を右クリックし、「RESTサービス」、「RESTサービスの削除」の順に選択します。)
希望するオブジェクトのRESTアクセスを個別に有効化します。
表またはビュー・レベル: 指定した表またはビューへのOracle REST Data Servicesアクセスを有効化するには、「接続」ナビゲータでその名前を右クリックし、「RESTサービスの有効化」の順に選択します。
使用方法の詳細は、SQL Developerのウィザードまたはダイアログ・ボックスの「ヘルプ」ボタンをクリックします。
この項では、Oracle REST Data Services問合せの使用例およびREST対応した後の表やビューに対するその他の操作の例を示します。
SQL Developerを使用して、表オブジェクトおよびビュー・オブジェクトを自動的にRESTfulサービスとして公開できます。この項では、これらのRESTfulサービスにアクセスする例を説明します。
ヒント:
こうした例は、これらのリソースにアクセスするのに使用するURLパターンを示しますが、クライアントはこれらのURLの構造の知識をハード・コーディングしないでください。かわりに、クライアントはリソースのハイパーリンクに従ってリソース間を移動してください。URLパターンの構造は、将来のリリースで進化したり、変更されたりする可能性があります。
この項では、RESTfulサービスを使用してオブジェクトにアクセスする例を説明します。
この例では、指定したスキーマの別名で、使用可能なリソースの一覧を取得します。表またはビューを自動的に有効化することで作成される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
のあるリンクはリソースを説明します。
この例では、個別オブジェクトのメタデータ(オブジェクトを説明するメタデータ)を取得しています。メタデータの場所は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/" } ] }
この例では、オブジェクトのデータを取得します。オブジェクトの各行は、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/" } ] }
この例では、結果データのページ区切りを制御するパラメータの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" } ] }
この例では、戻されるオブジェクトを制限するフィルタ句を指定します。
パターン: 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" } ] }
この例では、オブジェクトを識別するキーの値を指定することでオブジェクトを取得します。
パターン: 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/" } ] }
この例では、オブジェクトにデータを挿入します。リクエストに付加するボディのデータは、挿入するデータを格納したJSONオブジェクトです。
オブジェクトに主キーがある場合、オブジェクトには主キー・フィールドに移入する挿入トリガーが必要です。表に主キーがない場合には、行のROWIDがアイテムの識別子として使用されます。
オブジェクトに主キー値を割り当てるトリガーがない場合、次の項「表の行の更新/挿入」で説明されているPUT操作をかわりに使用してください。
パターン: POST http://<HOST>:<PORT>/ords/<SchemaAlias>/<ObjectAlias>/
例:
curl -i -H "Content-Type: application/json" -X POST -d "{ \"empno\" :7, \"ename\": \"JBOND\", \"job\":\"SPY\", \"deptno\" :11 }" "http://localhost:8080/ords/ordstest/emp/ Content-Type: application/json { "empno" :7, "ename": "JBOND", "job":"SPY", "deptno" :11 }
結果:
{ "empno": 7, "ename": "JBOND", "job": "SPY", "mgr": null, "hiredate": null, "sal": null, "comm": null, "deptno": 11, "links": [ { "rel": "self", "href": "http://localhost:8080/ords/ordstest/emp/7" }, { "rel": "edit", "href": "http://localhost:8080/ords/ordstest/emp/7" }, { "rel": "describedby", "href": "http://localhost:8080/ords/ordstest/metadata-catalog/emp/item" }, { "rel": "collection", "href": "http://localhost:8080/ords/ordstest/emp/" } ] }
この例では、オブジェクト内のデータを挿入または更新します(「アップサート」とも呼ばます)。リクエストに付加するボディのデータは、挿入または更新するデータを格納した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/" } ] }
この例では、フィルタ句で指定されたオブジェクトのデータを削除します。
パターン: DELETE http://<HOST>:<PORT>/ords/<SchemaAlias>/<ObjectAlias>/?q=<FilterClause>
例: curl -i -X DELETE http://localhost:8080/ords/ordstest/emp/?q={"deptno":11}"
結果:
{ "itemsDeleted": 1 }
この例では、バッチ・ロード機能を使用してオブジェクトのデータを挿入します。リクエストに付加するボディのデータはCSVファイルです。バッチ操作の動作はオプションの問合せパラメータを使用して制御できます。このパラメータは表3-1で説明しています。
パターン: POST http://<HOST>:<PORT>/ords/<SchemaAlias>/<ObjectAlias>/batchload?<Parameters>
パラメータ:
表3-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
この項では、REST対応の表やビューに対する問合せでのフィルタリングの例を示し、説明します。
フィルタリングは、全コレクションで見つかった項目のサブセットが含まれている複数ページのリソース全体に対し、リクエストごとの動的フィルタ定義を使用してコレクション・リソースを制限する処理です。フィルタリングは、大規模なコレクションの効率的な走査を可能にします。
問合せでフィルタリングするには、q=
FilterObjectパラメータを含め、FilterObjectはリソースに適用するカスタムな選択やソートを表すJSONオブジェクトです。たとえば、次のようなリソースを仮定します。
https://example.com/ords/scott/emp/
次の問合せには、ENAME列を「JOHN」に制限するフィルタが含まれています。
https://example.com/ords/scott/emp/?q={"ENAME":"JOHN"}
FilterObject
は、次の構文に準拠したJSONオブジェクトである必要があります。
FilterObject { orderby , asof, wmembers }
orderby
、asof
およびwmembers
属性はオプションで、その定義は次のとおりです。
orderby "$orderby": {orderByMembers} orderByMembers orderByProperty orderByProperty , orderByMembers orderByProperty columnName : sortingValue sortingValue "ASC" "DESC" "-1" "1" -1 1 asof "$asof": date "$asof": "datechars" "$asof": scn "$asof": +int wmembers wpair wpair , wmembers wpair columnProperty complexOperatorProperty columnProperty columnName : string columnName : number columnName : date columnName : simpleOperatorObject columnName : complexOperatorObject columnName : [complexValues] columnName "\p{Alpha}[[\p{Alpha}]]([[\p{Alnum}]#$_])*$" complexOperatorProperty complexKey : [complexValues] complexKey : simpleOperatorObject complexKey "$and" "$or" complexValues complexValue , complexValues complexValue simpleOperatorObject complexOperatorObject columnObject columnObject {columnProperty} simpleOperatorObject {simpleOperatorProperty} complexOperatorObject {complexOperatorProperty} simpleOperatorProperty "$eq" : string | number | date "$ne" : string | number | date "$lt" : number | date "$lte" : number | date "$gt" : number | date "$gte" : number | date "$instr" : string "$ninstr" : string "$like" : string "$null" : null "$notnull" : null "$between" : betweenValue betweenValue [null , betweenNotNull] [betweenNotNull , null] [betweenRegular , betweenRegular] betweenNotNull number date betweenRegular string number date
データ型の定義には次のものがあります。
string JSONString number JSONNumber date {"$date":"datechars"} scn {"$scn": +int}
説明:
datechars is an RFC3339 date format in UTC (Z) JSONString "" " chars " chars char char chars char any-Unicode-character except-"-or-\-or-control-character \" \\ \/ \b \f \n \r \t \u four-hex-digits JSONNumber int int frac int exp int frac exp int digit digit1-9 digits - digit - digit1-9 digits frac . digits exp e digits digits digit digit digits e e e+ e- E E+ E-
FilterObject
はRFC3986の第2.1項に従って符号化する必要があります。
FilterObject
の記述における演算子の例を次に示します。
ORDER BY property ($orderby) Order by with literals { "$orderby": {"SALARY": "ASC","ENAME":"DESC"} } Order by with numbers { "$orderby": {"SALARY": -1,"ENAME": 1} } ASOF property ($asof) With SCN (Implicit) { "$asof": 1273919 } With SCN (Explicit) { "$asof": {"$scn": "1273919"} } With Date (Implicit) { "$asof": "2014-06-30T00:00:00Z" } With Date (Explicit) { "$asof": {"$date": "2014-06-30T00:00:00Z"} } EQUALS operator ($eq) (Implicit and explicit equality supported._ Implicit (Support String and Dates too) { "SALARY": 1000 } Explicit { "SALARY": {"$eq": 1000} } Strings { "ENAME": {"$eq":"SMITH"} } Dates { "HIREDATE": {"$date": "1981-11-17T08:00:00Z"} } NOT EQUALS operator ($ne) Number { "SALARY": {"$ne": 1000} } String { "ENAME": {"$ne":"SMITH"} } Dates { "HIREDATE": {"$ne": {"$date":"1981-11-17T08:00:00Z"}} } LESS THAN operator ($lt) (Supports dates and numbers only) Numbers { "SALARY": {"$lt": 10000} } Dates { "SALARY": {"$lt": {"$date":"1999-12-17T08:00:00Z"}} } LESS THAN OR EQUALS operator ($lte) (Supports dates and numbers only) Numbers { "SALARY": {"$lte": 10000} } Dates { "HIREDATE": {"$lte": {"$date":"1999-12-17T08:00:00Z"}} } GREATER THAN operator ($gt) (Supports dates and numbers only) Numbers { "SALARY": {"$gt": 10000} } Dates { "SALARY": {"$gt": {"$date":"1999-12-17T08:00:00Z"}} } GREATER THAN OR EQUALS operator ($gte) (Supports dates and numbers only) Numbers { "SALARY": {"$gte": 10000} } Dates { "HIREDATE": {"$gte": {"$date":"1999-12-17T08:00:00Z"}} } In string operator ($instr) (Supports strings only) { "ENAME": {"$instr":"MC"} } Not in string operator ($ninstr) (Supports strings only) { "ENAME": {"$ninstr":"MC"} } #### LIKE operator ($like) (Supports strings. Eescape character not supported to try to match expressions with _ or % characters.) { "ENAME": {"$like":"AX%"} } #### BETWEEN operator ($between) (Supports string, dates, and numbers) Numbers { "SALARY": {"$between": [1000,2000]} } Dates { "SALARY": {"$between": [{"$date":"1989-12-17T08:00:00Z"},{"$date":"1999-12-17T08:00:00Z"}]} } Strings { "ENAME": {"$between": ["A","C"]} } Null Ranges ($lte equivalent) (Supported by numbers and dates only) { "SALARY": {"$between": [null,2000]} } Null Ranges ($gte equivalent) (Supported by numbers and dates only) { "SALARY": {"$between": [1000,null]} } #### NULL operator ($null) { "ENAME": {"$null": null} } #### NOT NULL operator ($notnull) { "ENAME": {"$notnull": null} } #### AND operator ($and) (Supports all operators, including $and and $or) Column context delegation (Operators inside $and will use the closest context defined in the JSON tree.) { "SALARY": {"$and": [{"$gt": 1000},{"$lt":4000}]} } Column context override (Example: salary greater than 1000 and name like S%) { "SALARY": {"$and": [{"$gt": 1000},{"ENAME": {"$like":"S%"}} ] } } Implicit and in columns ``` { "SALARY": [{"$gt": 1000},{"$lt":4000}] } ``` High order AND (All first columns and or high order operators -- $and and $ors -- defined at the first level of the JSON will be joined and an implicit AND) (Example: Salary greater than 1000 and name starts with S or T) { "SALARY": {"$gt": 1000}, "ENAME": {"$or": [{"$like":"S%"}, {"$like":"T%"}]} } Invalid expression (operators $lt and $gt lack column context) { "$and": [{"$lt": 5000},{"$gt": 1000}] } Valid alternatives for the previous invalid expression { "$and": [{"SALARY": {"$lt": 5000}}, {"SALARY": {"$gt": 1000}}] } { "SALARY": [{"$lt": 5000},{"$gt": 1000}] } { "SALARY": {"$and": [{"$lt": 5000},{"$gt": 1000}]} } OR operator ($or) (Supports all operators including $and and $or) Column context delegation (Operators inside $or will use the closest context defined in the JSON tree) { "ENAME": {"$or": [{"$eq":"SMITH"},{"$eq":"KING"}]} } Column context override (Example: name starts with S or salary greater than 1000) { "SALARY": {"$or": [{"$gt": 1000},{"ENAME": {"$like":"S%"}} ] } }
この項では、HTTP(S)を介してPL/SQLをリモート・プロシージャ・コール(RPC)のために利用可能にする方法について説明します。
自動PL/SQL機能は、ステートレスなWebサービス環境でエンコーディングとデータ転送の整合性を提供するために標準を使用します。この機能を使用すると、ORDSを介してパッケージ・レベルでOracle DatabaseのストアドPL/SQLファンクションおよびプロシージャを有効化できます。ビューや表を有効化する方法と同様です。
PL/SQLサブプログラムの自動有効化
PL/SQLプロシージャ
PL/SQLファンクション
PL/SQLパッケージ
PL/SQLパッケージ内のファンクションおよびプロシージャはPL/SQLパッケージ・オブジェクトの範囲内で名前を付けられているオブジェクトなので、個々に有効化することはできません。このため、粒度レベルがパッケージ・レベルでオブジェクトを有効化します。この粒度レベルは、そのパブリック・ファンクションおよびプロシージャをすべて公開可能にします。
注意:
オーバーロードしたパッケージ・ファンクションとプロシージャはサポートされていません。この項では、この機能によってサポートされるメソッドおよびコンテンツ・タイプについて説明します。
注意:
この機能はRPCスタイルのインタラクションを行うため、CRUDからHTTPメソッドへの標準データ・マッピングには適用できません。サポートされるコンテンツ・タイプは、application/json
です。
この項では、ORDSを介してPL/SQLオブジェクトを自動的に有効化する方法を説明します。
ORDS PL/SQL APIを使用してPL/SQLオブジェクトを有効化できます。
PL/SQLパッケージを有効化するには、次のサンプル・コード・スニペットに示すように、ORDS 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; /
例3-1 PL/SQLファンクションの有効化
PL/SQLファンクションを有効化するには、次のサンプル・コード・スニペットに示すように、ORDS 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; /
例3-2 PL/SQLプロシージャの有効化
PL/SQLプロシージャを有効化するには、次のサンプル・コード・スニペットに示すように、ORDS 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; /
この項では、SQL Developer 4.2以降を使用してPL/SQLオブジェクトを有効化する方法を説明します。
SQL Developerを使用してPL/SQLオブジェクト(たとえば、パッケージ)を有効化するには、次の手順を実行します。
注意:
これでパッケージ、ファンクションおよびプロシージャを有効化できるようになりました。ただし、有効化の粒度は、パッケージ全体レベル、スタンドアロン・ファンクション・レベル、またはスタンドアロン・プロシージャ・レベルのいずれかです。SQL Developerで、次の図に示すようにパッケージを右クリックします。
「RESTfulサービスを有効にする」を選択して、次のウィザード・ページを表示します。
オブジェクトの有効化: このオプションを有効にします(つまり、パッケージのRESTアクセスを有効にします)。
オブジェクト別名: オブジェクト別名としてregistry_pkg
を受け入れます。
承認が必要: 簡潔性を保つため、このオプションは無効にしておきます。
ウィザードのRESTfulサマリー・ページで「終了」をクリックします。
HTTPエンドポイントは、有効なデータベース・オブジェクトに対してリクエストに応じて動的に生成されます。ORDSは、問合せを使用してエンドポイントを生成するために、接続したデータベース・カタログを使用します。
HTTPエンドポイントを生成するため、すべてのデータベース・オブジェクトに対して次のルールが適用されます。
名前はすべて小文字に変換されます
エンドポイントがすでに割り当てられていなければ、生成されます
ストアド・プロシージャおよびストアド・ファンクションのエンドポイント
ファンクションまたはプロシージャ名は、同じネームスペースの表やビューと同じ方法でURL内に生成されます。
例3-3 ストアド・プロシージャのためのエンドポイントの生成
CREATE OR REPLACE PROCEDURE MY_SCHEMA.MY_PROC IS BEGIN NULL; END;
http://localhost:8080/ords/my_schema/my_proc/
例3-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
のエンドポイントは、オーバーロードしているため生成されません。入力ペイロードは、REST標準に従った値を持つJSONドキュメントです。
ペイロードは、次のコード・スニペットに示すように、INまたはIN OUTの各パラメータに対する名前/値ペアを含んでいる必要があります。
{ "p1": "abc", "p2": 123, "p3": null }
注意:
INまたはIN OUTパラメータがない場合、次のコード・スニペットに示すように、空のJSONボディが必要です。{ }
この項では、SQLおよびPL/SQLを使用して手動でRESTful Servicesを作成する方法を説明し、JSONドキュメントを使用してRESTリクエストのボディにあるストアド・プロシージャにパラメータを渡す方法を表示します。
RESTリクエスト(たとえばPOST
またはPUT
メソッド)のボディでJSONを使用できます。ここで、各パラメータはJSONの名前/値ペアです。
URIの必須パラメータに対して、および他の特別な事例でルート・パターンを使用して、ボディを持たないRESTリクエスト(GET
メソッドなど)のパラメータを指定できます。
URIのオプションのパラメータに対して、および他の特別な事例で問合せ文字列を使用して、ボディを持たないRESTリクエスト(GET
メソッドなど)のパラメータを指定できます。
パラメータ引き渡しタスク実行前に完了しておく必要がある前提条件セットアップ・タスク
この前提条件セットアップ情報は、「RESTfulサービスのスタート・ガイド」の項の手順1および2を完了していることを前提にしています。そこでは、ordstest
スキーマおよびemp
データベース・テーブルをREST対応にし(手順1)、SQL問合せからRESTfulサービスを作成、テストしました(手順2)。これら2つの手順を、パラメータ引き渡しタスクを実行する前に完了する必要があります(次以降のサブセクションを参照)。
関連トピック
この項では、RESTリクエスト(たとえばPOST
またはPUT
メソッド)のボディでJSONドキュメントを使用してストアド・プロシージャにパラメータを渡す方法を示します(各パラメータは名前/値ペア)。この操作はレコード上で更新を実行し、その結果、レコードに対する変更がOUT
パラメータとして戻されます。
次の手順を実行します。
注意:
すべてのパラメータはオプションです。 JSONドキュメントでパラメータの名前/値ペアを省略すると、パラメータはNULL
に設定されます。
名前/値ペアは、JSONドキュメント内に、任意の順序で並べることができます。 JSONを使用すると、JSONドキュメントでこの点に多くの柔軟性を得られます。
1レベルのJSONのみサポートされます。JSONオブジェクトまたは配列をネストすることはできません。
GET
メソッドなど)。まず、多くのバインド変数を持つemp
表で、問合せに対してGET
メソッド・ハンドラを作成します。この手順では、ルート・パターンを使用して、必要なパラメータ値を指定します。
ルート・パターンを使用していくつかの必要なパラメータ値を持つGET
メソッドを送信するには、次の手順を実行します。
問合せは、Ward、MartinおよびTurnerという名のセールスマンに対応する3件のレコードを戻します。
関連項目:
ルート・パターンの詳細は、ORDSディストリビューションに含まれるドキュメントdocs/javadoc/plugin-api/route-patterns.html
と、ドキュメント「Oracle REST Data Servicesのルート・パターン」を参照してください。
この項では、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」を入力します(次の図を参照)。
図3-10 問合せ文字列を使用してGETメソッドとともにいくつかのパラメータ名/値ペアを送信した結果をブラウザを使用して表示する
この問合せは、名前がTurner、部門が30、給与が1500、管理者が7698であるセールスマンに対応する1件のレコードを戻します。
パラメータ値をURLエンコードするのは有効です。必ずしも必要ではないこともありますが、行っても安全です。これにより、インターネットにより何かが改変されること、たとえば、特殊文字が障害を引き起こす可能性がある他の文字に変換されることを防げます。RESTクライアントにこの機能があることもありますし、フレーズurlエンコーダ
でインターネットを検索することでその機能があるツールを見つけることもできます。
URIでパラメータ・リストの末尾に決してバックスラッシュを入れないでください。そうしないと、404 Not Found
エラーが表示される場合があります。
関連項目:
JSONを使用してパラメータ値を渡す経験をさらに充実させるには、ORDSチュートリアル(OBE)の演習4およびデータベース・アプリケーション開発仮想イメージを参照します。
この項では、Oracle Database 12c リリース2 (12.2)で利用できるSQL/JSONデータベース・ファンクションを使用して、ネストされたJSONオブジェクトと階層関係表を互いにマップするために説明します。
この項には次のトピックが含まれます:
この項では、ネスト配列を持つJSONオブジェクトを複数の階層的な関係表に挿入する方法を説明します。
この機能を実装するために使用される2つの主要なテクノロジは次のとおりです。
ORDSが提供してPOSTおよび他のRESTコールのボディにあるJSONおよび他のコンテンツをPL/SQL RESTハンドラに配信する:body
バインド変数
Oracle Database 12cリリース2 (12.2)で提供されるJSON_TABLEおよびその他のSQL/JSON演算子
関係表にデータを挿入するためのこれらのテクノロジを使用する利点のいくつかを次に示します。
機能を実装するための要件が最小限です。たとえば、JSONパーサー・ソフトウェアのインストールは不要です
JSONからの関係マッピングが単純な場合、書くのも読むのも簡単な、単純な宣言型コードを使用できます
より複雑なマッピングを処理する機能は強力で洗練されています。次のものが含まれます。
NULLSおよびブール値をマッピングするためのメカニズム
JSONを処理するための洗練されたメカニズム。JSONは時間とともに進化します。このため、マッピング・コードは、JSONドキュメントの古いバージョンも新しいバージョンも処理できる必要があります。
たとえば、単純なスカラー値が進化して、複数のスカラーまたはネストされたスカラー値やオブジェクトの配列を含むJSONオブジェクトになる場合があります。スカラー値を戻すSQL/JSON演算子は、単純なスカラーがこれらのより精巧な構造内に埋め込まれた場合でも、引き続き機能できます。特別なメカニズム(Ordinality列と呼ばれます)を使用して、値が導出されたところから構造を決定することができます。
関連項目:
この項では、:body
バインド変数を使用するために役に立つヒントをいくつか提供します。
:body
バインド変数を使用する際に役に立ついくつかのヒントを次に示します。:body
バインド変数は、一度のみ、アクセスまたは参照解除できます。以降のアクセスは、NULL値を戻します。このため、2つのJSON_Table操作で使用するには、その前にローカルのL_PO
変数に:body
にバインド変数を割り当てる必要があります。
:body
バインド変数はBLOBデータ型であり、BLOB変数にのみ割り当てることができます。
注意:
L_PO
はBLOB変数なので、JSON_TABLEファンクションの式の後にFORMAT JSON
句を使用する必要があります。詳細は項を参照。:body
バインド変数は、画像データなど、他のタイプのデータとともに使用できます。
関連項目:
開発チュートリアル: 画像ギャラリの作成。画像データを持つ:body
バインド変数の使用の作業例。
Database SQL言語リファレンス
この項では、ネストされたLineItemsがあるJSON発注書を取得し、PurchaseOrder表の行およびLineItem表の行に挿入する例を示します。
例3-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}]}'
この項では、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));
この項では、POSTリクエストに対応するサンプルのPL/SQLハンドラ・コードを示します。ハンドラ・コードは、PurchaseOrder表の行およびLineItem表の行に発注書を挿入するために使用されます。
例3-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;
この項では、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サービスを作成するには、次のいずれかの方法を使用します。
ORDS PL/SQL APIを使用して、POST挿入のためにRESTサービスとハンドラを定義します。次に、PurchaseOrderおよびLineItem表を含むデータベース・サーバー上のjsontable
スキーマに接続します。
注意:
JSON_TABLEおよび他のSQL/JSON演算子は、エスケープする必要があるため、一重引用符を使用します。たとえば、すべての一重引用符(’)を二重引用符(“)に置き換える必要があります。SQL Developerで、ORDSの「REST開発」ペインを使用してRESTサービスを定義します。
この項では、Oracle REST Data Services (ORDS) PL/SQL APIを使用して、POST挿入のためにREST Serviceとハンドラを定義する方法を示します。
代替として、SQL DeveloperでORDSの「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;
この項では、Oracle REST Data Servicesを使用して、階層(親/子)関係内の関係表を問い合わせ、ネストされたJSON形式でデータを戻す方法を説明します。
この機能を実装するために使用される2つの主要なテクノロジは次のとおりです。
Oracle Database 12c リリース2 (12.2)で利用できる新しいSQL/JSONファンクション。json_objects
を使用して関係表からJSONオブジェクトを生成したり、json_arrayagg
を使用してネストされた(子)関係表からネストされたJSON配列を生成したりできます。
RESTサービス・ハンドラが次の種類のデータを戻すSQL問合せを実行できるようにするために使用されるORDSメディア・ソース・タイプ:
データのHTTP Content-Type (この場合はapplication/json)
json_object
によって戻されるJSONデータ
この手法を使用する利点のいくつかを次に示します。
機能を実装するための要件が最小限です。たとえば、JSONパーサー・ソフトウェアのインストールは不要です
書きやすく読みやすいシンプルな宣言型コーディングにより、JSONオブジェクトから関係表へのマッピングがシンプルになる。
より複雑なマッピングを処理する機能は強力で洗練されています。これには、NULLSおよびブール値をマッピングするためのメカニズムが含まれます。
たとえば、Oracle DatabaseのNULLは、JSON要素の欠如、またはJSONのNULL値に変換できます。Oracle Database はブール型を格納しませんが、SQL/JSONファンクションでは、データベース内の文字列または数値の値をブーリアンのTRUEまたはFALSEの値にマッピングできます。
この項では、ネストされたJSON発注書の形式でPurchaseOrderおよびLineItem関係表に挿入したデータを問い合わせるか、GETする方法を説明します。
例3-7 関係表上でOracle REST Data Servicesの問合せを使用してネストされたJSONオブジェクトを生成するGETハンドラ・コード
SELECT 'application/json', json_object('PONumber' VALUE po.PONo, 'Requestor' VALUE po.Requestor, 'CostCenter' VALUE po.CostCenter, 'Address' VALUE json_object('street' VALUE po.AddressStreet, 'city' VALUE po.AddressCity, 'state' VALUE po.AddressState, 'zipCode' VALUE po.AddressZip, 'country' VALUE po.AddressCountry), 'LineItems' VALUE (select json_arrayagg( json_object('ItemNumber' VALUE li.ItemNumber, 'Part' VALUE json_object('Description' VALUE li.PartDescription, 'UnitPrice' VALUE li.PartUnitPrice, 'UPCCode' VALUE li.PartUPCCODE), 'Quantity' VALUE li.Quantity)) FROM LineItem li WHERE po.PONo = li.PONo)) FROM PurchaseOrder po WHERE po.PONo = :id
この項では、作成したモジュールに新しいテンプレートを作成するためのORDS PL/SQL APIコールの例を提供します。
例3-8 demoモジュールに新しいtest/:id テンプレートおよびGETハンドラを作成するためのORDS 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;
この項では、Oracleデータベースにアクセスして結果をJSON形式で取得するためにPOSTおよびGET RESTful Servicesをテストする方法を示します。
この項には次のトピックが含まれます:
この項では、JSON発注書のデータベースへの挿入をテストする方法を表示します。
URIパターン: http://<HOST>:<PORT>/ords/<SchemaAlias>/<module>/<template>
例:
メソッド: POST
URIパターン: http://localhost:8080/ords/ordstest/demo/test/
po1.json
のようにファイルを作成します。{"PONumber" : 1608, "Requestor" : "Alexis Bull", "CostCenter" : "A50", "Address" : {"street" : "200 Sporting Green", "city" : "South San Francisco", "state" : "CA", "zipCode" : 99236, "country" : "United States of America"}, "LineItems" : [ {"ItemNumber" : 1, "Part" : {"Description" : "One Magic Christmas", "UnitPrice" : 19.95, "UPCCode" : 1313109289}, "Quantity" : 9.0}, {"ItemNumber" : 2, "Part" : {"Description" : "Lethal Weapon", "UnitPrice" : 19.95, "UPCCode" : 8539162892}, "Quantity" : 5.0}]}'
curl -i -H "Content-Type: application/json" -X POST -d @po1.json "http://localhost:8080/ords/ordstest/demo/test/"cURLコマンドは、次のレスポンスを戻します。
HTTP/1.1 200 OK Transfer-Encoding: chunked
ORDSを使用すると、開発者は、Oracle Database、Oracle Database 12c JSONドキュメント・ストアおよびOracle NoSQL DatabaseへのRESTインタフェースを可能な限り短時間で簡単に作成できます。Oracle Databaseで作業する場合、開発者は表に対してAutoREST機能を使用したり、より複雑な操作のためにSQLおよびPL/SQLルーチンを使用してカスタム・モジュールを作成したりできます。
文字列中の日付をエンコーディングするために、ORDSはRFC3339標準を使用します。通常、使用される日付形式はdd-mmm-yyyyです(例: 15-Jan-2017)。ORDSは、Oracle Databaseで値の挿入や更新などの操作を実行したときに、指定された形式のJSON文字列をOracle日付データ型に自動的に変換します。JSON文字列に再変換する場合、ORDSはOracle日付データ型を文字列形式に自動的に変換します。
注意:
JSONは日付データ型をサポートしませんが、Oracle Databaseは日付データ型をサポートします。この項には次のトピックが含まれます:
関連項目:
時刻やタイムゾーンの処理方法などの詳細は次のページを参照してください: https://jsao.io/2016/10/working-with-dates-using-ords/
データがRESTリクエストから到着すると、Oracle REST Data Services (ORDS)がISO 8601文字列を解析し、Oracle DatabaseのTIMESTAMP
データ型に変換する場合があります。これは、AutoREST (POST
およびPUT
)でも、カスタム・モジュールのバインド変数でも発生します。TIMESTAMP
がタイムゾーン関連のコンポーネントをサポートしないのを思い出してください。このため、DATETIME
値が、変換処理時にORDSが使用するタイムゾーンに設定されます。
RESTリクエストへのレスポンスを作成する場合、ORDSはOracle DatabaseのDATETIME
値をズールー語のISO 8601文字列に変換します。これは、AutoREST (GET
)と、SQL問合せ(GET)にマッピングされるカスタム・モジュールで発生します。DATE
およびTIMESTAMP
データ型の場合、タイムゾーン関連のコンポーネントを持たないため、タイムゾーンはORDSが実行されているタイムゾーンとみなされ、ズールー語への変換はそこから行われます。
ORDSがデータベースのデータに従って適切なタイムゾーンを使用していることを確認します(たとえば、日付をデータベースに入れたいタイムゾーン)。
NLS設定(time_zone)をストリーム中で変更しないでください。
ISO 8601文字列について説明していますが、ORDSは実際には文字列をサポートしている点に注意してください。RFC3339文字列はISO 8601文字列に準拠しているサブセットです。JSON.stringify(date)
によって戻されるデフォルトの形式がサポートされます。
警告:
TIMESTAMP WITH TIME ZONE
またはTIMESTAMP WITH LOCAL TIME ZONE
への暗黙的なデータ変換に関する問題を防止するために、ORDSが使用するタイムゾーンは、セッション・タイムゾーンとの同期を維持することが重要です。デフォルトでORDSは自動的にこれを行いますが、開発者はALTER SESSION
文でセッション・タイムゾーンを変更できます。
関連項目:
RFC3339Oracle REST Data Services (ORDS)の起動時に、それにより内部で実行されるJVMは、ORDSが様々なタイムゾーン変換に使用するタイムゾーンを取得およびキャッシュします。デフォルトで、タイムゾーンはオペレーティング・システム(OS)から取得されるため、ORDSが使用するタイムゾーンを変更する簡単な方法は、OSのタイムゾーンを変更し、続いてORDSまたはそれが実行されているアプリケーション・サーバーを再起動することです。言うまでもなく、タイムゾーンを変更するための指示は、オペレーティング・システムにより異なります。
もしなんらかの理由でOSと同じタイムゾーンを使用したくない場合、Java環境変数Duser.timezone
を使用してデフォルトをオーバーライドすることができます。その変数が正確にはどのように設定されているかは、スタンドアロン・モードとJavaアプリケーション・サーバーのどちらで実行されているかにより異なります。次のトピックではいくつか例を示します。
スタンドアロン・モード
ORDSをスタンドアロン・モードで実行する場合、-jar
オプションの前のコマンドライン・オプションとして指定することで、Java環境変数を設定できます。
例3-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
という名前のスクリプトを作成することで環境変数を設定します。
例3-10 Duser.timezone Java環境変数のJavaアプリケーション・サーバーでの設定
次のコード例は、Javaアプリケーション・サーバー — Tomcat 8でタイムゾーンを設定するための、setenv.sh
スクリプトの内容を示しています。
CATALINA_TIMEZONE="-Duser.timezone=America/New_York" CATALINA_OPTS="$CATALINA_OPTS $CATALINA_TIMEZONE
最近のORDSリリース(3.0.X)をサポートするSQL Developerを使用してORDSアプリケーションを開発することを強くお薦めします。Application Expressは、RESTおよびORDSの基本概念を学ぶために役立つチュートリアルを提供します。ただし、チュートリアルは以前のORDSリリース(2.0.X)を使用しています。使用方法のチュートリアルで説明されている役に立つヒントのいくつかを次に示します。
Application Expressインスタンスがサンプルのアプリケーションおよびサンプルのデータベース・オブジェクトを自動的にワークスペースに追加するように構成されている場合、リソース・モジュールのリストにoracle.example.hr
という名前のサンプルのリソース・モジュールが表示されます。リソース・モジュールがリストにない場合は、RESTfulサービス・ページの右側にあるサンプル・データのリセットタスクをクリックし、サンプルのリソース・モジュールを作成できます。
この項では、RESTfulサービスへのセキュアなアクセスの構成方法について説明します。
RESTful APIは、それぞれのリソースが一意のURIを持つ複数のリソースから構成されています。リソースのセットは権限によって保護できます。権限はロールのセットを定義し、認証済のユーザーのうちの少なくとも1人は、権限によって保護されたリソースへのアクセス権を持っている必要があります。
特定の権限によって保護されるリソースを構成するには、権限のマッピングを作成する必要があります。権限のマッピングは、権限が保護するリソースを特定するパターンのセットを定義します。
トピック:
ユーザーは、ファースト・パーティのCookieベースの認証またはサード・パーティのOAuth 2.0ベースの認証を使用して認証できます。
トピック:
ファースト・パーティは、RESTful APIの作成者です。ファースト・パーティのアプリケーションは、RESTful APIと同じWebオリジンにデプロイされたWebアプリケーションです。ファースト・パーティのアプリケーションは、Webアプリケーションが使用しているものと同じCookieセッションを使用し、RESTful APIに自身を認証し、権限を付与することが可能です。ファースト・パーティのアプリケーションにはRESTful APIへの完全なアクセス権があります。
サード・パーティは、RESTful APIの作成者以外のパーティです。サード・パーティのアプリケーションは、ファースト・パーティのアプリケーションと同じようには信頼できません。そのため、サード・パーティ製のアプリケーションに対し、選択的に制限付きのRESTful APIへのアクセス権を付与するための仲介手段が必要となります。
OAuth 2.0プロトコルは、RESTful APIへの条件付きおよび制限アクセスを提供するフローを定義します。簡単に言えば、サード・パーティのアプリケーションは、まずファースト・パーティに登録する必要があり、その後、ファースト・パーティ(またはファースト・パーティのRESTfulサービスのエンド・ユーザー)が、そのサード・パーティ・アプリケーションに対する期限の短いアクセス・トークンを発行することで、サード・パーティ・アプリケーションのRESTful APIへの制限付きアクセスを承認します。
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の所有者が承認する必要があります。
リソースにアクセスするための権限は、次のデータで構成されます。
名前: 権限の一意の識別子。この値は必須です。
ラベル: OAuthを使用してユーザーが権限へのアクセスを承認するように求められるとき、エンド・ユーザーに提示される権限の名前。権限がThree-LeggedのOAuthフローで使用される場合、この値は必須です。
説明: 権限の目的の説明。これも、ユーザーが権限へのアクセスを承認するように求められるとき、エンド・ユーザーに提示されます。権限がThree-LeggedのOAuthフローで使用される場合、この値は必須です。
ロール: 権限に関連付けられているロール名のセット。認証されたパーティは、権限で保護されたリソースへのアクセスを許可されるために、指定されたロールの少なくとも1つを持っている必要があります。値は必須ですが、空のセットとすることはでき、それはユーザーの認証は必要だが、権限にアクセスするための特定のロールは必要ないことを示します。
Two-LeggedのOAuthフローでは、サード・パーティのアプリケーション(OAuthの用語ではクライアントと呼ばれる)は、必要なロールの少なくとも1つを持つ必要があります。
Three-LeggedのOAuthフローでは、サード・パーティのアプリケーションからのアクセス・リクエストを承認するエンド・ユーザーは、必要なロールの少なくとも1つを持つ必要があります。
権限は一連のロールを列挙し、ユーザーはロールを持つことはできますが、これらのロールはどこに定義されるのでしょう。ロールを持っているユーザーについてはどうでしょう。彼らはどこに定義されているのでしょう。
権限は一連のロールを列挙し、ユーザーはロールを持つことができます。Oracle REST Data Servicesは、ユーザー管理のタスクをOracle REST Data Servicesがデプロイされているアプリケーション・サーバーに委任します。Oracle REST Data Servicesでは、アプリケーション・サーバーによって定義および管理されるユーザーを認証でき、認証されたユーザーが所属するロールおよびグループを識別できます。アプリケーション・サーバーのユーザー・リポジトリを構成することも、アプリケーション・サーバーにOracle REST Data Servicesをデプロイするパーティの責任です。
ユーザー・リポジトリを定義したり、既存のユーザー・リポジトリと統合したり、アプリケーション・サーバーはいろいろな方法で構成できるため、アプリケーション・サーバーのユーザー・リポジトリを構成する方法はこのドキュメントでは説明できません。詳細は、アプリケーション・サーバーのドキュメントを参照してください。
Oracle REST Data Servicesでは、簡易なファイルベースのユーザー・リポジトリ・メカニズムが提供されます。ただし、このユーザー・リポジトリはデモおよびテストのみを目的としており、本番使用はサポートされていません。
このリポジトリにユーザーを作成する方法の詳細は、次のように、ユーザー・コマンドのコマンドライン・ヘルプを参照してください。
java -jar ords.war help user
形式:
java -jar ords.war user <user> <roles>
引数:
<user>
はユーザーのユーザーIDです。
<roles>
はユーザーが持つロール(ゼロ以上)のリストです。
関連トピック
このチュートリアルでは、次のOAuth機能を使用し、リソースのセットを保護するための権限を作成し、保護されたリソースにアクセスする方法を示します。
クライアント資格証明
認可コード
暗黙のフロー
また、ファースト・パーティCookieベースの認証を使用してリソースにアクセスする方法を示します。
トピック:
この項では、様々なOAuthフロー機能の用途を説明します。
ファースト・パーティCookieベースの認証は、RESTful APIと同じオリジンでホストされるWebアプリケーションからRESTful APIにアクセスするときに使用します。
認可コード・フローは、RESTful APIにアクセスするサード・パーティのWebアプリケーションを許可する必要があり、そのサード・パーティ・アプリケーションが、安全にクライアントの資格証明を保持できる独自のWebサーバーを持っている場合に使用します。これは、ほとんどのWebアプリケーションの標準的な状況で、サード・パーティのアプリケーションは、アプリケーションの再認証をユーザーに促すことなく、リフレッシュ・トークンを使用してユーザー・セッションの存続期間を延長でき、最高のセキュリティと最高のユーザー・エクスペリエンスを提供できます。
暗黙のフローは、サード・パーティのアプリケーションがその資格証明を安全に保持できるWebサーバーを持たない場合に使用します。このフローは、サード・パーティの単一ページ・ベースのアプリケーションで役立ちます。暗黙のフローではリフレッシュ・トークンを発行できないので、ユーザーはアプリケーションを認証するように頻繁に促されます。
ネイティブ・モバイルやデスクトップのアプリケーションは、認可コードまたは暗黙のフローを使用する必要があります。それらは、Webブラウザの画面にサイン・インおよび認可のプロンプトを表示し、認可処理の最後にWebブラウザの画面からアクセス・トークンを取得する必要があります。
クライアント資格証明フローは、RESTful APIによって管理されるデータへのアクセスを承認するようにユーザーに要求せず、サード・パーティのアプリケーションにRESTful APIへの直接アクセスを提供する必要がある場合に使用します。このサード・パーティのアプリケーションは、資格証明の機密を保持できるサーバー・ベースのアプリケーションである必要があります。クライアント資格証明はいつでもネイティブの実行可能ファイル内で検出できるため、クライアント資格証明フローはネイティブ・アプリケーションでは使用しないでください。
このチュートリアルでは、次のことが前提となっています。
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/
リソースのセットを保護してアクセスするには、次の手順を実行します。
スキーマを有効にします。ORDSTESTスキーマに接続し、次のPL/SQL文を実行します。
begin ords.enable_schema; commit; end;
リソースを作成します。ORDSTESTスキーマに接続し、次のPL/SQL文を実行します。
begin ords.create_service( p_module_name => 'examples.employees' , p_base_path => '/examples/employees/', p_pattern => '.' , p_items_per_page => 7, p_source => 'select * from emp order by empno desc'); commit; end;
このコードにより、この後の手順で権限で保護する/examples/employees/
リソースが作成されます。
次のようにcURLコマンドを実行して、リソースを確認できます。
curl -i https://example.com/ords/ordstest/examples/employees/
結果は次のようになるはずです(読みやすくするために編集しています)。
Content-Type: application/json Transfer-Encoding: chunked { "items": [ {"empno":7934,"ename":"MILLER","job":"CLERK","mgr":7782,"hiredate":"1982-01-23T00:00:00Z","sal":1300,"comm":null,"deptno":10}, ... ], "hasMore":true, "limit":7, "offset":0, "count":7, "links": [ {"rel":"self","href":"https://example.com/ords/ordstest/examples/employees/"}, {"rel":"describedby","href":"https://example.com/ords/ordstest/metadata-catalog/examples/employees/"}, {"rel":"first","href":"https://example.com/ords/ordstest/examples/employees/"}, {"rel":"next","href":"https://example.com/ords/ordstest/examples/employees/?offset=7"} ] }
権限を作成します。ORDSTESTスキーマに接続し、次のPL/SQL文を実行します。
begin ords.create_role('HR Administrator'); ords.create_privilege( p_name => 'example.employees', p_role_name => 'HR Administrator', p_label => 'Employee Data', p_description => 'Provide access to employee HR data'); commit; end;
このコードにより、ORDSTESTスキーマに属するロールと権限が作成されます。
ロール名は一意である必要があり、印刷可能な文字のみを含める必要があります。
権限名は一意である必要があり、OAuth 2.0仕様の第3.3項のスコープ名で指定されている構文に準拠する必要があります。
Three-Leggedの認可コードおよび暗黙のフローでこの権限を使用する場合は、ラベルおよび権限の説明を用意する必要があります。このラベルおよび説明は、Three-Leggedフローの承認フェーズでエンド・ユーザーに提示されます。
値は、その権限の名前と目的を識別するプレーン・テキストである必要があります。
USER_ORDS_PRIVILEGESビューの問合せで、権限が正しく作成されたことを確認できます。
select id,name from user_ords_privileges where name = 'example.employees';
結果は次のようになるはずです。
ID NAME ----- ----------------- 10260 example.employees
IDの値はデータベースによって異なりますが、NAMEの値はこのように表示されるはずです。
権限をリソースと関連付けます。ORDSTESTスキーマに接続し、次のPL/SQL文を実行します。
begin ords.create_privilege_mapping( p_privilege_name => 'example.employees', p_pattern => '/examples/employees/*'); commit; end;
このコードは、example.employees
権限を/examples/employees/
というリソース・パターンと関連付けます。
USER_ORDS_PRIVILEGE_MAPPINGSビューの問合せで、権限が正しく作成されたことを確認できます。
select privilege_id, name, pattern from user_ords_privilege_mappings;
結果は次のようになるはずです。
PRIVILEGE_ID NAME PATTERN ------------ -------------------- --------------------- 10260 example.employees /examples/employees/*
PRIVILEGE_IDの値はデータベースによって異なりますが、NAMEおよびPATTERNの値はこのように表示されるはずです。
次のcURLコマンドを実行し、/examples/employees/
リソースがexample.employees
権限で保護されていることを確認できます。
curl -i https://example.com/ords/ordstest/examples/employees/
結果は次のようになるはずです(読みやすくするために再フォーマットしています)。
HTTP/1.1 401 Unauthorized Content-Type: text/html Transfer-Encoding: chunked <!DOCTYPE html> <html> ... </html>
保護されたリソースにファースト・パーティの認証を介してアクセスできることを、次の手順で確認できます。
エンド・ユーザーを作成します。ファイルベースのユーザー・リポジトリを使用して、examples.employees
権限にアクセスするために必要なHR管理者のロールを持つテスト・ユーザーを作成します。コマンド・プロンプトで次のコマンドを実行します。
java -jar ords.war user "hr_admin" "HR Administrator"
パスワードの入力を求められたら、入力し、確認します。
エンド・ユーザーとしてサイン・インします。Webブラウザに次のURLを入力します。
https://example.com/ords/ordstest/examples/employees/
アクセスが拒否されたことを示すページで、サイン・インへのリンクをクリックします。
HR_ADMINユーザーのために登録した資格証明を入力し、「サインイン」をクリックします。
ページがhttps://example.com/ords/ordstest/examples/employees/
にリダイレクトされること、およびJSONドキュメントが表示されることを確認します。
OAuthクライアントを登録します。ORDSTESTスキーマに接続し、次のPL/SQL文を実行します。
begin oauth.create_client( p_name => 'Client Credentials Example', p_grant_type => 'client_credentials', p_privilege_names => 'example.employees', p_support_email => 'support@example.com'); commit; end;
このコードは、クライアント資格証明のOAuthフローを使用してexamples.employees
権限にアクセスする、Client Credentials Example
という名前のクライアントを登録します。
次のSQL文を実行し、クライアントが登録されたこと、およびexamples.employees
権限へのアクセスがリクエストされたことを確認できます。
select client_id,client_secret from user_ords_clients where name = 'Client Credentials Example';
結果は次のようになるはずです。
CLIENT_ID CLIENT_SECRET -------------------------------- ------------------------ o_CZBVkEMN23tTB-IddQsQ.. 4BJXceufbmTki-vruYNLIg..
CLIENT_IDおよびCLIENT_SECRETの値は、OAuthクライアントの機密の資格証明を表します。これらの値は、記録して安全に保管する必要があります。これは、クライアント・アプリケーションのユーザーIDおよびパスワードと考えることができます。
OAuthクライアントに必要な権限を付与します。ORDSTESTスキーマに接続し、次のPL/SQL文を実行します。
begin oauth.grant_client_role( 'Client Credentials Example', 'HR Administrator'); commit; end;
このコードは、クライアント資格証明のOAuthフローを使用してexamples.employees
権限にアクセスする、Client Credentials Example
という名前のクライアントを登録します。
次のSQL文を実行することで、クライアントにロールが付与されたことを確認できます。
select * from user_ords_client_roles where client_name = 'Client Credentials Example';
結果は次のようになるはずです。
CLIENT_ID CLIENT_NAME ROLE_ID ROLE_NAME ---------- --------------------------- -------- ---------------------- 10286 Client Credentials Example 10222 HR Administrator
クライアントの資格証明を使用してのOAuthのアクセス・トークンを取得します。
OAuthプロトコルでは、HTTPリクエストに、クライアント資格証明フローを使用して作成したアクセス・トークンを使用しなければならないと明記されています。[rfc6749-4.4.]。
リクエストは、トークン・エンドポイントと呼ばれる、周知のURLとして作成する必要があります。Oracle REST Data Servicesのトークン・エンドポイントのパスは常にoauth/tokenで、アクセスされるスキーマのルート・パスからの相対です。この例のトークン・エンドポイントは次のとおりです。
https://example.com/ords/ordstest/oauth/token
次のcURLコマンドを実行します。
curl -i --user clientId:clientSecret --data "grant_type=client_credentials" https://example.com/ords/ordstest/oauth/token
このコマンドで、clientId
をClient Credentials Example
のUSER_ORDS_CLIENTS内のCLIENT_IDの値で置き換え、clientSecret
をClient Credentials Example
のUSER_ORDS_CLIENTS内のCLIENT_SECRETの値で置き換えます。出力は次のようになります。
HTTP/1.1 200 OK Content-Type: application/json { "access_token": "2YotnFZFEjr1zCsicMWpAA", "token_type": "bearer", "expires_in":3600 }
この出力では、アクセス・トークンはbearer
タイプで、その値はaccess_token
フィールドで指定されています。この値はリクエストごとに異なります。expires_in
の値は、アクセス・トークンの有効期限が切れるまでの秒数を示し、この例のトークンは1時間(3600秒)で期限切れになります。
アクセス・トークンを使用して保護されたリソースにアクセスします。次のcURLコマンドを実行します。
curl -i -H"Authorization: Bearer accessToken" https://example.com/ords/ordstest/examples/employees/
このコマンドで、accessToken
が前の手順で示したaccess_token
フォールドの値で置き換えられます。出力は次のようになります。
Content-Type: application/json Transfer-Encoding: chunked { "items": [ {"empno":7934,"ename":"MILLER","job":"CLERK","mgr":7782,"hiredate":"1982-01-23T00:00:00Z","sal":1300,"comm":null,"deptno":10}, ... ], "hasMore":true, "limit":7, "offset":0, "count":7, "links": [ {"rel":"self","href":"https://example.com/ords/ordstest/examples/employees/"}, {"rel":"describedby","href":"https://example.com/ords/ordstest/metadata-catalog/examples/employees/"}, {"rel":"first","href":"https://example.com/ords/ordstest/examples/employees/"}, {"rel":"next","href":"https://example.com/ords/ordstest/examples/employees/?offset=7"} ] }
認可コード用のクライアントを登録します。ORDSTESTスキーマに接続し、次のPL/SQL文を実行します。
begin oauth.create_client( p_name => 'Authorization Code Example', p_grant_type => 'authorization_code', p_owner => 'Example Inc.', p_description => 'Sample for demonstrating Authorization Code Flow', p_redirect_uri => 'http://example.org/auth/code/example/', p_support_email => 'support@example.org', p_support_uri => 'http://example.org/support', p_privilege_names => 'example.employees' ); commit; end;
このコードは、認可コードのOAuthフローを使用してexamples.employees
権限にアクセスする、Authorization Code Example
という名前のクライアントを登録します。実際のアプリケーションでは、認可コードをリダイレクトして戻すURIを用意する必要があり、有効なサポート電子メール・アドレスを指定する必要があります。この例では、架空のデータおよびサンプルのWebサービスexample.org
を使用しています。
次のSQL文を実行し、クライアントが登録されたこと、およびexamples.employees
権限へのアクセスがリクエストされたことを確認できます。
select id, client_id, client_secret from user_ords_clients where name = 'Authorization Code Example';
結果は次のようになるはずです。
ID CLIENT_ID CLIENT_SECRET ---------- -------------------------------- -------------------------------- 10060 IGHso4BRgrBC3Jwg0Vx_YQ.. GefAsWv8FJdMSB30Eg6lKw..
権限へのアクセス権を付与するには、エンド・ユーザーがアクセスを承認する必要があります。CLIENT_IDおよびCLIENT_SECRETの値は、OAuthクライアントの機密の資格証明を表します。これらの値は、記録して安全に保管する必要があります。これは、クライアント・アプリケーションのユーザーIDおよびパスワードと考えることができます。
認可コードを使用してOAuthアクセス・トークンを取得します。この手順には、いくつかのサブ手順があります。(前の手順でHR_ADMINエンド・ユーザーを作成しておく必要があります。)
OAuth認可コードを取得します。
エンド・ユーザーには、サイン・インおよびサード・パーティ・アプリケーションへのアクセスを承認するためのプロンプトを表示する(Webページを介して)必要があります。サード・パーティ・アプリケーションは、OAuthの認可エンドポイントにユーザーを誘導することによってこのプロセスを開始します。Oracle REST Data Servicesの認可エンドポイントのパスは常にoauth/auth
で、アクセスされるスキーマのルート・パスからの相対です。この例のトークン・エンドポイントは次のとおりです。
https://example.com/ords/ordstest/oauth/auth
OAuth 2.0プロトコルでは、認可リクエストのURIに、問合せ文字列に特定のパラメータを含める必要があると明記されています。
response_type
パラメータには、code
の値が必要です。
client_id
パラメータには、アプリケーションのクライアント識別子の値が含まれている必要があります。これは前の手順で決定したclient_id
の値です。
state
パラメータには、一意の推測できない値が含まれている必要があります。この値には、2つの目的があります。それは、クライアント・アプリケーションが各認可リクエストを一意に識別する方法を提供すること(それにより、任意のアプリケーション固有の状態を値に関連付け、その値をアプリケーション自身のセッション識別子と考える)、およびクライアント・アプリケーションがクロス・サイト・リクエスト・フォージェリ(CSRF)攻撃から身を守る手段を提供することです。state
の値は、認可プロセスの最後にリダイレクトURIに戻されます。クライアントは、その値がアプリケーションによって開始された認可リクエストのものであることを確認する必要があります。クライアントが状態の値を検証できない場合は、認可リクエストが攻撃者によって開始されたものとみなし、リダイレクトを無視してください。
認可リクエストを開始するには、Webブラウザで次のURLを入力します。
https://example.com/ords/ordstest/oauth/auth?response_type=code&client_id=cliendId&state=uniqueRandomValue
このURIは、clientId
を以前に注目したCLIENT_ID列の値と置き換え、uniqueRandromValue
を一意の推測できない値に置き換えます。クライアント・アプリケーションは、この値を記憶し、認可フローの最後にリダイレクトの一部として戻されるstate
パラメータと照合する必要があります。
client_id
が認識された場合、サイン・インのプロンプトが表示されます。エンド・ユーザーHR_ADMINの資格証明を入力して「サインイン」をクリックし、次のページで「承認」をクリックすると、クライアントが登録されたときに指定したリダイレクトURIへリダイレクトされます。リダイレクトURIは、URIの問合せ文字列部分に認可コードが含まれます。また、クライアントがフローの開始時に指定したものと同じstate
パラメータの値が含まれます。リダイレクトURIは次のようになります。
http://example.org/auth/code/example/?code=D5doeTSIDgbxWiWkPl9UpA..&state=uniqueRandomValue
クライアント・アプリケーションは、state
パラメータの値を検証し、アクセス・トークンの取得に使用するcode
パラメータの値を記録する必要があります。
OAuthのアクセス・トークンを取得します。
サード・パーティ・アプリケーションは、認可コードを取得した後、それをアクセス・トークンと交換する必要があります。サード・パーティ・アプリケーションのサーバーは、トークン・エンドポイントにHTTPSリクエストを行う必要があります。次の例のようにcURLコマンドを使用して、このリクエストを行うサーバーを模倣できます。
curl --user clientId:clientSecret --data "grant_type=authorization_code&code=authorizationCode" https://example.com/ords/ordstest/oauth/token
このコマンドで、clientId
をAuthorization Code Example
のUSER_ORDS_CLIENTSにあるCLIENT_IDの値と置き換え、clientSecret
をAuthorization Code Example
のUSER_ORDS_CLIENTSにあるCLIENT_SECRETの値と置き換え、authorizationCode
を前の手順で記録した認可コードの値(code
パラメータの値)と置き換えます。
結果は次のようになるはずです。
HTTP/1.1 200 OK Content-Type: application/json { "access_token": "psIGSSEXSBQyib0hozNEdw..", "token_type": "bearer", "expires_in":3600, "refresh_token": "aRMg7AdWPuDvnieHucfV3g.." }
この結果では、アクセス・トークンがaccess_token
フィールドで指定され、リフレッシュ・トークンがrefresh_token
フィールドで指定されています。このリフレッシュ・トークンの値は、ユーザーにサード・パーティ・アプリケーションの再認可を求めることなく、ユーザー・セッションを延長するために使用できます。
アクセス・トークンを使用して保護されたリソースにアクセスします。
サード・パーティ・アプリケーションでは、OAuthのアクセス・トークンを取得した後、そのアクセス・トークンを使用して保護された/examples/employees/
リソースにアクセスできます。
curl -i -H"Authorization: Bearer accessToken" https://example.com/ords/ordstest/examples/employees/
このコマンドで、accessToken
が前の手順で示したaccess_token
フォールドの値で置き換えられます。
結果は次のようになるはずです。
Content-Type: application/json Transfer-Encoding: chunked { "items": [ {"empno":7934,"ename":"MILLER","job":"CLERK","mgr":7782,"hiredate":"1982-01-23T00:00:00Z","sal":1300,"comm":null,"deptno":10}, ... ], "hasMore":true, "limit":7, "offset":0, "count":7, "links": [ {"rel":"self","href":"https://example.com/ords/ordstest/examples/employees/"}, {"rel":"describedby","href":"https://example.com/ords/ordstest/metadata-catalog/examples/employees/"}, {"rel":"first","href":"https://example.com/ords/ordstest/examples/employees/"}, {"rel":"next","href":"https://example.com/ords/ordstest/examples/employees/?offset=7"} ] }
リフレッシュ・トークンを使用してセッションを延長します。
サード・パーティ・アプリケーションは、いつでも、リフレッシュ・トークンの値を使用して新規の存続期間を持つ新規のアクセス・トークンを生成できます。これにより、サード・パーティ・アプリケーションは自由にユーザー・セッションを延長できます。このためには、サード・パーティ・アプリケーションのサーバーは、トークン・エンドポイントにHTTPSリクエストを行う必要があります。次の例のようにcURLコマンドを使用して、このリクエストを行うサーバーを模倣できます。
curl --user clientId:clientSecret --data “grant_type=refresh_token&refresh_token=refreshToken" https://example.com/ords/ordstest/oauth/token
このコマンドで、clientId
をClient Credentials Client
のUSER_ORDS_CLIENTSにあるCLIENT_IDの値と置き換え、clientSecret
をClient Credentials Client
のUSER_ORDS_CLIENTSにあるCLIENT_SECRETの値と置き換え、refreshToken
を前の手順で取得したrefresh_token
の値と置き換えます。
結果は次のようになるはずです。
HTTP/1.1 200 OK Content-Type: application/json { "access_token": "psIGSSEXSBQyib0hozNEdw..", "token_type": "bearer", "refresh_token": "aRMg7AdWPuDvnieHucfV3g..", "expires_in": 3600 }
この結果では、アクセス・トークンがaccess_token
フィールドで指定され、新規リフレッシュ・トークンがrefresh_token
フィールドで指定されています。このリフレッシュ・トークンの値は、ユーザーにサード・パーティ・アプリケーションの再認可を求めることなく、ユーザー・セッションを延長するために使用できます。(前のアクセス・トークンおよびリフレッシュ・トークンは無効となり、そのかわりに新規の値を使用する必要があることに注意してください。)
暗黙のフローのクライアントを登録します。ORDSTESTスキーマに接続し、次のPL/SQL文を実行します。
begin oauth.create_client( p_name => 'Implicit Example', p_grant_type => 'implicit', p_owner => 'Example Inc.', p_description => 'Sample for demonstrating Implicit Flow', p_redirect_uri => 'http://example.org/implicit/example/', p_support_email => 'support@example.org', p_support_uri => 'http://example.org/support', p_privilege_names => 'example.employees' ); commit; end;
このコードは、暗黙のOAuthフローを使用してexamples.employees
権限にアクセスする、Implicit Example
という名前のクライアントを登録します。実際のアプリケーションでは、認可コードをリダイレクトして戻すURIを用意する必要があり、有効なサポート電子メール・アドレスを指定する必要があります。この例では、架空のデータおよびサンプルのWebサービスexample.org
を使用しています。
次のSQL文を実行し、クライアントが登録されたこと、およびexamples.employees
権限へのアクセスがリクエストされたことを確認できます。
select id, client_id, client_secret from user_ords_clients where name = 'Implicit Example';
結果は次のようになるはずです。
ID CLIENT_ID CLIENT_SECRET ---------- -------------------------------- -------------------------------- 10062 7Qz--bNJpFpv8qsfNQpS1A..
権限へのアクセス権を付与するには、エンド・ユーザーがアクセスを承認する必要があります。
暗黙のフローを使用してのOAuthのアクセス・トークンを取得します。(前の手順でHR_ADMINエンド・ユーザーを作成しておく必要があります。)
エンド・ユーザーには、サイン・インおよびサード・パーティ・アプリケーションへのアクセスを承認するためのプロンプトを表示する(Webページを介して)必要があります。サード・パーティ・アプリケーションは、OAuthの認可エンドポイントにユーザーを誘導することによってこのプロセスを開始します。Oracle REST Data Servicesの認可エンドポイントのパスは常にoauth/auth
で、アクセスされるスキーマのルート・パスからの相対です。この例のトークン・エンドポイントは次のとおりです。
https://example.com/ords/ordstest/oauth/auth
OAuth 2.0プロトコルでは、認可リクエストのURIに、問合せ文字列に特定のパラメータを含める必要があると明記されています。
response_type
パラメータには、token
の値が必要です。
client_id
パラメータには、アプリケーションのクライアント識別子の値が含まれている必要があります。これは前の手順で決定したclient_id
の値です。
state
パラメータには、一意の推測できない値が含まれている必要があります。この値には、2つの目的があります。それは、クライアント・アプリケーションが各認可リクエストを一意に識別する方法を提供すること(それにより、任意のアプリケーション固有の状態を値に関連付け、その値をアプリケーション自身のセッション識別子と考える)、およびクライアント・アプリケーションがクロス・サイト・リクエスト・フォージェリ(CSRF)攻撃から身を守る手段を提供することです。state
の値は、認可プロセスの最後にリダイレクトURIに戻されます。クライアントは、その値がアプリケーションによって開始された認可リクエストのものであることを確認する必要があります。クライアントが状態の値を検証できない場合は、認可リクエストが攻撃者によって開始されたものとみなし、リダイレクトを無視してください。
認可リクエストを開始するには、Webブラウザで次のURLを入力します。
https://example.com/ords/ordstest/oauth/auth?response_type=token&client_id=cliendId&state=uniqueRandomValue
このURIは、clientId
を以前に注目したCLIENT_ID列の値と置き換え、uniqueRandromValue
を一意の推測できない値に置き換えます。クライアント・アプリケーションは、この値を記憶し、認可フローの最後にリダイレクトの一部として戻されるstate
パラメータと照合する必要があります。
client_id
が認識された場合、サイン・インのプロンプトが表示されます。エンド・ユーザーHR_ADMINの資格証明を入力して「サインイン」をクリックし、次のページで「承認」をクリックすると、クライアントが登録されたときに指定したリダイレクトURIへリダイレクトされます。リダイレクトURIは、URIの問合せ文字列部分にアクセス・トークンが含まれます。また、クライアントがフローの開始時に指定したものと同じstate
パラメータの値が含まれます。リダイレクトURIは次のようになります。
http://example.org/auth/code/example/#access_token=D5doeTSIDgbxWiWkPl9UpA..&type=bearer&expires_in=3600&state=uniqueRandomValue
クライアント・アプリケーションは、state
パラメータの値を検証し、そのアクセス・トークンの値をメモする必要があります。
アクセス・トークンを使用して保護されたリソースにアクセスします。次のcURLコマンドを実行します。
curl -i -H "Authorization: Bearer accessToken" https://example.com/ords/ordstest/examples/employees/
このコマンドで、accessToken
が前の手順で示したaccess_token
フォールドの値で置き換えられます。出力は次のようになります。
Content-Type: application/json Transfer-Encoding: chunked { "items": [ {"empno":7934,"ename":"MILLER","job":"CLERK","mgr":7782,"hiredate":"1982-01-23T00:00:00Z","sal":1300,"comm":null,"deptno":10}, ... ], "hasMore":true, "limit":7, "offset":0, "count":7, "links": [ {"rel":"self","href":"https://example.com/ords/ordstest/examples/employees/"}, {"rel":"describedby","href":"https://example.com/ords/ordstest/metadata-catalog/examples/employees/"}, {"rel":"first","href":"https://example.com/ords/ordstest/examples/employees/"}, {"rel":"next","href":"https://example.com/ords/ordstest/examples/employees/?offset=7"} ] }
Oracle REST Data Servicesでは、少数のユーザー・ロールが事前定義されています。
RESTful Services
- 保護されたRESTfulサービスに関連付けられたデフォルトのロールです。
OAuth2 Client Developer
- OAuth 2.0のアプリケーションを登録するユーザーはこのロールが必要です。
SQL Developer
- Oracle SQL Developerを使用してRESTfulサービスを開発するユーザーはこのロールが必要です。
SODA Developer
- これは、SODA REST APIにアクセスする必要があるデフォルト・ロールです。このロールの詳細は、『Oracle REST Data Services SODA for REST開発者ガイド』を参照してください。
Listener Administrator
- Oracle SQL Developerを介してOracle REST Data Servicesのインスタンスを管理するユーザーはこのロールが必要です。通常、java -jar ords.war user
コマンドによって作成されたユーザーのみがこのロールを持ちます。
Listener Administrator
ロールによりOracle REST Data Servicesのインスタンスを構成でき、その結果、そのインスタンスで処理されるすべてのApplication Expressのワークスペースに影響を与えることが可能となるため、Application ExpressユーザーはListener Administrator
ロールを取得することを許可されません。
トピック:
デフォルトでは、Oracle Application ExpressのユーザーはOracle REST Data Servicesの事前定義済ユーザー・ロールを持っていません。これは、デフォルトでは、Application Expressのユーザーは次のことができないことを意味します。
保護されたRESTfulサービスの起動
OAuth 2.0アプリケーションの登録
Oracle SQL Developerを使用したRESTfulサービスの開発
これは、Application Expressの開発者および管理者を含め、すべてのApplication Expressユーザーに適用されます。そこで、Application Expressのユーザーを適切なユーザー・グループに追加して前述のアクションを実行できるようにするため、次の手順に従うことを覚えておくことが重要です。
トピック:
Application Expressユーザーに前述のロールのいずれかを付与するには、ユーザーをロールに対応するApplication Expressのユーザー・グループに追加する必要があります。たとえば、RESTEASY_ADMIN
ユーザーにRESTful Services
ロールを付与するには、次の手順を実行します。
RESTEASY_ADMIN
でRESTEASY
ワークスペースにログインします。RESTEASY_ADMIN
ユーザーの左にある編集アイコンをクリックします。「RESTfulサービス」
を選択します。Application Expressユーザーを適切なユーザー・グループに追加するのは、手順を見落としがちで、管理するユーザーが多い場合は反復的なタスクとなります。
この問題に対処するため、defaults.xml
構成ファイルを変更し、Application Expressユーザーに自動的に事前定義済のRESTfulサービス・ロールのセットを付与するようにOracle REST Data Servicesを構成できます。
このファイルには、Oracle REST Data Servicesがロールを構成するための3つのプロパティ設定が定義されています。
apex.security.user.roles
- 開発者または管理者ではない通常のユーザーに付与するロールのカンマ区切りのリスト。
apex.security.developer.roles
- Developer
アカウントの権限を持つユーザーに付与するロールのカンマ区切りのリスト。Developer
は、apex.security.user.roles
設定で定義されているロールも継承します。
apex.security.administrator.roles
- Administrator
アカウントの権限を持つユーザーに付与するロールのカンマ区切りのリスト。Administrator
は、apex.security.user.roles
およびapex.security.developer.roles
設定で定義されているロールも継承します。
たとえば、自動的に、すべてのユーザーにRESTful Services
権限を付与し、すべての開発者および管理者にOAuth2 Client Developer
およびSQL Developer
ロールを付与するには、defaults.xml
構成ファイルに次のように追加します。
<!-- Grant all Application Express Users the ability to invoke protected RESTful Services --> <entry key="apex.security.user.roles">RESTful Services</entry> <!-- Grant Application Express Developers and Administrators the ability to register OAuth 2.0 applications and use Oracle SQL Developer to define RESTful Services --> <entry key="apex.security.developer.roles"> OAuth2 Client Developer, SQL Developer</entry>
defaults.xml
構成ファイルを変更したら、Oracle REST Data Servicesを再起動する必要があります。
組込みのRESTful Service
ロールは、保護されたRESTfulサービスにアクセスすることを許可されたユーザーの識別に役立つデフォルトです。
しかし、特定のRESTfulサービスにアクセスできるユーザーのセットを制限するため、きめ細かいロール定義が必要になることもあります。
トピック:
RESTfulサービスのロールは、Application Expressのユーザー・グループです。ギャラリRESTfulサービスへのアクセスを制御するためにユーザー・グループを作成するには、次の手順に従います。 (
ワークスペース管理者としてRESTEASY
ワークスペースにログインします。
「管理」に移動し、「ユーザーとグループの管理」に移動します。
「グループ」タブをクリックします。
「ユーザー・グループの作成」をクリックします。
「名前」にGallery Users
と入力します。
「グループの作成」をクリックします。
ユーザー・グループを作成したら、それをRESTful権限と関連付けることができます。ギャラリ・ユーザーのロールをexample.gallery
権限に関連付けるには、次の手順に従います。
ギャラリ・ユーザー
を選択します。この変更で、ユーザーはギャラリRESTfulサービスにアクセスできるギャラリ・ユーザー・ロールを持ちます。
関連項目:
この手順では、例として「開発チュートリアル: イメージ・ギャラリの作成」のイメージ・ギャラリ・アプリケーションを使用します。Oracle REST Data Servicesでは、WebLogic ServerおよびGlassFishによって提供されるAPIを使用し、資格証明(ユーザー名とパスワード)を検証し、ユーザーがメンバーであるグループおよびロールのセットを取得できます。
この項では、WebLogic ServerおよびGlassFishによって提供される組込みのユーザー・リポジトリでユーザーを作成し、そのユーザーに対して認証を行う機能を検証します。
このドキュメントではWebLogic ServerおよびGlassFishをLDAPリポジトリなどの多くの一般的なユーザー・リポジトリ・システムと統合する方法は説明しませんが、WebLogic ServerまたはGlassFishが正しく構成されていれば、Oracle REST Data Servicesでそのようなリポジトリに対して認証が可能です。アプリケーション・サーバーでどのようなユーザー・リポジトリがサポートされているか、およびそれらのリポジトリへのアクセスを構成する方法の詳細は、アプリケーション・サーバーのドキュメントを参照してください。
トピック:
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アプリケーションの登録が許可されます。
では、ユーザーを正常に認証できることを検証します。
作成したWebLogic Serverユーザーが正常に認証されることを検証するには、次の手順を実行します。
アプリケーションが1つもリストされていない状態でOAuth 2.0クライアントの登録ページが表示されるはずです。このページが表示された場合は、WebLogic Serverのユーザー・リポジトリに対する認証が機能していることを検証できたことになります。
「ユーザーには、リソースにアクセスする権限がありません。」
というメッセージとともにサインオンのプロンプトが再表示される場合は、誤りを犯しています(おそらく、グループ・リストの値のスペルミス)。
GlassFishに対してのユーザー認証には、大きな手順として次のものがあります。
サンプルのGlassFishユーザーを作成するには、次の手順を実行します。
3rdparty_dev2
という名前のユーザーが作成され、OAuth2 Client Developer
という名前のグループのメンバーになります。これは、このユーザーがOAuth2 Client Developer
ロールを取得することを意味し、それによりOAuth 2.0アプリケーションの登録が許可されます。
では、ユーザーを正常に認証できることを検証します。
「GlassFishユーザーの作成」で作成したWebLogic Serverユーザーが正常に認証されることを検証するには、次の手順を実行します。
アプリケーションが1つもリストされていない状態でOAuth 2.0クライアントの登録ページが表示されるはずです。このページが表示された場合は、WebLogic Serverのユーザー・リポジトリに対する認証が機能していることを検証できたことになります。
「ユーザーには、リソースにアクセスする権限がありません。」
というメッセージとともにサインオンのプロンプトが再表示される場合は、誤りを犯しています(おそらく、グループ・リストの値のスペルミス)。
他の項の例で、WebLogic ServerおよびGlassFishの組込みのユーザー・リポジトリの構成方法を説明しています。そのような状況では、ユーザー・グループの名前の付け方を完全に制御できます。ユーザーがロールとまったく同じ(大文字/小文字を区別)名前を持つグループのメンバーである場合、そのユーザーはそのロールを持っていると考えられます。
しかし、既存のユーザー・リポジトリと統合する場合は、RESTfulサービスの開発者がユーザー・リポジトリ内のユーザー・グループの命名や編成を制御できないことがあります。このような状況では、ユーザー・リポジトリに定義された既存の「物理」ユーザーグループをOracle REST Data ServicesまたはRESTfulサービス(あるいはその両方)で定義された「論理」ロールにマッピングするメカニズムが必要とされます。
このグループからロールへのマッピングは、Oracle REST Data Servicesではrole-mapping.xml
という名前の構成ファイルを構成することで実現されます。
トピック:
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
ロールの両方を付与します。
トピック:
グループまたはロールの数が多い場合には、各グループから各ロールに明示的にマッピングするのは拡張性がよくありません。この問題に対処するため、ルールをパラメータ化できます。次の例を考えてみます。
<?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テンプレートに使用するものと同じで、パラメータ名が中カッコ({}
)で区切られます。
グループのルールで定義された任意のパラメータは、ロールのルールでも間接参照できます。次の例を考えてみます。
<?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
という名前の論理ロールにマッピングされます。
必要なロール・マッピングを実現するため、複数の中間的なルールの適用を必要とする場合もあります。次の例を考えてみます。
<?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
ロールにマッピングされます。
Oracle REST Data Servicesには、多くの操作でSQL Developerのグラフィカル・インタフェースのかわりに使用できるPL/SQL API (アプリケーション・プログラミング・インタフェース)があります。使用可能なサブプログラムは次のPL/SQLパッケージに含まれています。
ORDS: 「ORDS PL/SQLパッケージのリファレンス」を参照
OAUTH: 「OAUTH PL/SQLパッケージのリファレンス」を参照
Oracle REST Data Services PL/SQL APIを使用するには、まず次の手順を実行する必要があります。
RESTfulサービスを開発するために使用するデータベースに、Oracle REST Data Servicesをインストールします。
RESTアクセス用に1つ以上のデータベース・スキーマを有効化します。
トピック:
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
という名前のオプションのパラメータが指定されます。
関連トピック
作成したRESTfulサービスをテストするために、まだ開始されていなければOracle REST Data Servicesを開始します。
java -jar ords.war
ブラウザでサービスのURIを入力します。次の例ではwhom
パラメータが指定されていないため、デフォルトでは現行ユーザーからJoe
に対して「Hello」の挨拶を表示します。
http://localhost:8080/ords/ordstest/examples/routes/greeting/Joe
この例の説明は、次のとおりです。
Oracle REST Data Servicesは、localhostで実行されていて、ポート8080でリスニングしています。
Oracle REST Data Servicesは、コンテキスト・パス/ords
でデプロイされています。
RESTfulサービスは、ordstest
と呼ばれるデータベース・スキーマで作成されました。
URLにはオプションのwhomパラメータが含まれていないため、:whomバインド・パラメータはnull値にバインドされ、その結果、問合せは現行データベース・ユーザー(sys_context(''USERENV'',''CURRENT_USER'')
)の値をかわりに使用することになります。
ブラウザにJSON表示拡張機能がある場合、次のような結果が表示されます。
{
"items": [
{
"greeting": "Hello Joe from ORDSTEST"
}
],
"hasMore": false,
"limit": 25,
"offset": 0,
"count": 1,
"links": [
{
"rel": "self",
"href": "http://localhost:8080/ords/ordstest/examples/routes/greeting/"
},
{
"rel": "describedby",
"href": "http://localhost:8080/ords/ordstest/metadata-catalog/examples/routes/greeting/"
},
{
"rel": "first",
"href": "http://localhost:8080/ords/ordstest/examples/routes/greeting/Joe"
}
]
}
次の例は、前述の例と類似していますが、オプションのパラメータwhom
が指定されていて、挨拶がJane
からであることを示しています。
http://localhost:8080/ords/ordstest/examples/routes/greeting/Joe?whom=Jane
今回は、次のような結果になります。
{
"items": [
{
"greeting": "Hello Joe from Jane"
}
],
"hasMore": false,
"limit": 25,
"offset": 0,
"count": 1,
"links": [
{
"rel": "self",
"href": "http://localhost:8080/ords/ordstest/examples/routes/greeting/"
},
{
"rel": "describedby",
"href": "http://localhost:8080/ords/ordstest/metadata-catalog/examples/routes/greeting/"
},
{
"rel": "first",
"href": "http://localhost:8080/ords/ordstest/examples/routes/greeting/Joe"
}
]
}
この結果では、:whom
バインド・パラメータがJane
値にバインドされているため、"from"の後にはORDSTEST
ではなくJane
が続くことに注意してください。