メインコンテンツまでスキップ
バージョン: 20 R6 BETA

権限

データ保護と、承認ユーザーによる迅速かつ容易なデータアクセスを両立することは、Webアプリケーションにとって大きな課題です。 ORDA のセキュリティアーキテクチャーはデータストアの中心に実装されており、プロジェクト内のさまざまなリソース (データストア、データクラス、関数など) に対して、すべての Web または REST ユーザーセッションに特定の権限を定義することができます。

概要

ORDA のセキュリティアーキテクチャーは、権限、許諾アクション (read、create など)、およびリソースの概念に基づいています。

Webユーザーまたは RESTユーザーがログインすると、そのセッションには自動的に関連する権限がロードされます。 権限は、session.setPrivileges() 関数によって、セッションに割り当てられます。

セッション内で送信されるユーザーリクエストは、プロジェクトの roles.json ファイルで定義された権限に対して評価されます。

権限外のアクションをユーザーが実行しようとすると、権限エラーが生成されるか、あるいは読み取り権限がない属性の場合にはそのデータは送信されません。

schema

参照

詳細なアクセス権限アーキテクチャーの概要については、完全な権限システムでデータアクセスをフィルタリングする ブログ記事を参照ください。

リソース

プロジェクト内の以下のリソースに対して、許諾アクションと権限名を割り当てることができます (この設定をパーミッションと呼びます):

  • データストア
  • データクラス
  • 属性 (計算属性およびエイリアス属性を含む)
  • データモデルクラス関数
  • シングルトン関数

セッションがリソースにアクセスするたびに (アクセス形式に関係なく)、4D はセッションの権限を確認し、許可されていない場合にはアクセスを拒否します。

あるレベルにおいて定義されたパーミッションは基本的に下位レベルに継承されますが、パーミッションは複数のレベルで設定することもできます:

  • データストアレベルで定義されたパーミッションは、自動的にすべてのデータクラスに割り当てられます。
  • データクラスレベルで定義されたパーミッションは、データストアの設定をオーバーライドします (あれば)。 デフォルトでは、データクラスのすべての属性が、データクラスのパーミッションを継承します。
  • データクラスとは異なり、属性レベルで定義されたパーミッションは、親のデータクラスの設定をオーバーライドするのではなく、それに追加されます。 たとえば、同じ許諾アクションに対し、データクラスのレベルでは "general" という権限名を、データクラスの属性のレベルでは "detail" という権限名を割り当てた場合、その属性にアクセスするには、セッションに "general" と "detail" の両方の権限が設定されている必要があります。
info

パーミッションは、データストアオブジェクトや関数へのアクセスを制御します。 特定の条件に基づいて読み取りデータをフィルタリングしたい場合は、制限付エンティティセレクション の利用がより適切かもしれません。

許諾アクション

利用可能なアクションは対象となるリソースによります。

アクションデータストアデータクラス属性データモデル関数またはシングルトン関数
create任意のデータクラスにおいてエンティティを作成当該データクラスにおいてエンティティを作成当該属性に許可されたデフォルト値とは異なる値を持つエンティティを作成 (エイリアス属性の場合は無視されます)n/a
read任意のデータクラスにおいて属性を読み取り当該データクラスにおいて属性を読み取り当該属性を読み取りn/a
update任意のデータクラスにおいて属性を更新当該データクラスにおいて属性を更新当該属性を更新 (エイリアス属性の場合は無視されます)n/a
drop任意のデータクラスにおいてデータを削除当該データクラスにおいてデータを削除当該属性の null でない値を削除 (エイリアス属性と計算属性を除く)n/a
executeプロジェクトの任意の関数を実行 (データストア、データクラス、エンティティセレクション、エンティティ)データクラスの任意の関数を実行。 データクラス関数、エンティティ関数、エンティティセレクション関数は、データクラスの関数として扱われます。n/a当該関数を実行
describe/rest/$catalog API ですべてのデータクラスが利用可能/rest/$catalog API で当該データクラスが利用可能/rest/$catalog API で当該属性が利用可能/rest/$catalog API で当該データクラス関数が利用可能 (シングルトン関数は利用できません)
promoten/an/an/a関数の実行に指定の権限を関連付けます。 権限は一時的にセッションに追加され、関数の実行終了とともに削除されます。 セキュリティ上、セッション全体ではなく、当該関数を実行するプロセスのみに権限が追加されます。

注:

  • エイリアス属性の元である属性に対するアクセス権をセッションが持っていない場合でも、エイリアス属性へのアクセス権があれば、これを読み取ることができます。
  • 計算属性を構成する属性に対するアクセス権をセッションが持っていない場合でも、計算属性へのアクセス権があれば、これを読み取ることができます。
  • シングルトンクラス (singleton 型) には許諾アクションを割り当てることができます。その場合、そのシングルトンクラスの公開関数すべて、および、シングルトン関数 (singletonMethod 型)に適用されます。
  • デフォルト値: 現在の実装では、Null のみデフォルト値として利用可能です。
  • REST の 強制ログインモード では、authentify()関数 は、権限の設定に関係なく常にゲストユーザーによって実行可能です。

許諾の設定は一貫している必要があります。とくに:

  • update および drop アクションには read が必要です (create には不要です)
  • データモデル関数の場合、promote アクションには describe が必要です。

権限とロール

権限 とは、リソース に対して アクション を実行する技術的な能力であり、ロール は、管理者が使用するために公開された権限のことです。 基本的にロールとは、ビジネスユーザーのプロフィールを定義するためにいくつかの権限を集めたものです。 たとえば、"manageInvoices" (請求書管理) は権限の例で、"secretary" (秘書) は ("manageInvoices" および他の権限を持つ) ロールの例です。

権限は、複数の "リソース+アクション" の組み合わせと関連付けることができます。 また、一つのアクションに複数の権限を関連付けることができます。 権限は、他の権限を含むことができます。

  • 権限やロールの 作成roles.json ファイル内にておこないます (後述参照)。 アクセス権の範囲を 設定 するには、リソースに適用される許諾アクションに権限名を割り当てます。

  • 各ユーザーセッションに権限やロールを 許可 するには、Session クラスの .setPrivileges() 関数を使用します。

例題

セッションにおいて特定のロールを許可します:


exposed Function authenticate($identifier : Text; $password : Text)->$result : Text

var $user : cs.UsersEntity

Session.clearPrivileges()

$result:="ゲストとしてログインしています"

$user:=ds.Users.query("identifier = :1"; $identifier).first()

If ($user#Null)
If (Verify password hash($password; $user.password))
Session.setPrivileges(New object("roles"; $user.role))
$result:=$user.role+"としてログインしています"
End if
End if



roles.json ファイル

roles.json ファイルは、プロジェクトのセキュリティ設定の全体を記述します。

デフォルトファイル

プロジェクトを作成すると、デフォルトの roles.json ファイルが次の場所に作成されます: <project folder>/Project/Sources/ (アーキテクチャー 参照)。

デフォルトのファイルには次の内容が含まれています:

/Project/Sources/roles.json

{
"privileges": [
{
"privilege": "none",
"includes": []
}
],

"roles": [],

"permissions": {
"allowed": [
{
"applyTo": "ds",
"type": "datastore",
"read": ["none"],
"create": ["none"],
"update": ["none"],
"drop": ["none"],
"describe": ["none"],
"execute": ["none"],
"promote": ["none"]
}
]
},

"forceLogin": true

}

最高レベルのセキュリティのため、データストア ("ds") のすべての許諾アクションに "none" の権限名が割り当てられています。したがって、デフォルトでは ds オブジェクト全体へのデータアクセスが無効になっています。 この "none" 権限はセキュリティのため、使用も変更もしないことが推奨されています。Web や RESTリクエストから利用可能にしたい各リソースには、それ専用の権限を新たに追加することが推奨されています (以下の例を参照)。

caution

roles.json ファイルに特定のパラメーターが定義されていない場合、アクセスは制限されません。 これにより、アクセスを気にすることなくアプリケーションを開発することができますが、本番環境では推奨されていません。

互換性

以前のリリースでは、roles.json ファイルはデフォルトで作成されませんでした。 4D 20 R6 以降、roles.jsonファイルを含まない、または "forceLogin": true の設定が含まれていない既存のプロジェクトを開く場合、設定ダイアログボックスの Web機能 ページds.authentify() 関数を通しての REST認証を有効化 ボタンが利用可能になります。 このボタンはセキュリティ設定を自動的にアップグレードします (コードを修正する必要があるかもしれません。このブログ記事を参照ください)。

Qodly Studio

Qodly Studio for 4D では、権限パネルの 強制ログインオプション を使用してログインモードを設定することができます。

シンタックス

roles.json ファイルの構文は次のとおりです:

プロパティ名必須説明
privilegesprivilege オブジェクトの Collection定義された権限のリスト
[].privilegeStringアクセス権の名称
[].includesString の Collection内包する権限名のリスト
rolesrole オブジェクトの Collection定義されたロールのリスト
[].roleStringロール名
[].privilegesString の Collection内包する権限名のリスト
permissionsオブジェクト設定されたパーミッションのリスト
allowedpermission オブジェクトの Collection許可されたパーミッションのリスト
[].applyToString対象の リソース
[].typeStringリソース タイプ: "datastore", "dataclass", "attribute", "method", "singletonMethod", "singleton"
[].readString の Collection権限名のリスト
[].createString の Collection権限名のリスト
[].updateString の Collection権限名のリスト
[].dropString の Collection権限名のリスト
[].describeString の Collection権限名のリスト
[].executeString の Collection権限名のリスト
[].promoteString の Collection権限名のリスト
forceLoginBoolean"forceLogin" モード を有効にする場合は true
注記
  • "WebAdmin" 権限名は、アプリケーションによって予約されています。 この名前をカスタムの権限名に使用することは推奨されません。
  • privileges および roles の名称においては文字の大小が区別されます。

Roles_Errors.json ファイル

roles.json ファイルは、4D 起動時に解析されます。 このファイルへの変更を反映させるには、アプリケーションを再起動する必要があります。

roles.json ファイルを解析する際にエラーが発生した場合、4D はプロジェクトを読み込みますが、グローバルアクセス保護は無効になります。これにより、開発者はエラー修正のためファイルにアクセスすることができます。 また、Roles_Errors.json という名前のエラーファイルが プロジェクトの Logs フォルダー に生成され、エラー行が記述されています。 このファイルは、roles.json ファイルのエラーがすべて修正されると、自動的に削除されます。

Roles_Errors.json ファイルが Logs フォルダー に存在するかどうか、起動時に確認することをお勧めします。存在する場合、解析エラーが発生し、アクセスが制限されないことを意味します。 たとえば、次のように書くことができます:

/Sources/DatabaseMethods/onStartup.4dm
If (Not(File("/LOGS/"+"Roles_Errors.json").exists))

Else // プロジェクトが開かれるのを防ぐことができます
ALERT("roles.json ファイルが不正なため、アプリケーションを終了します。")
QUIT 4D
End if

権限設定の例

グッドプラクティスは、"none" 権限によってすべてのデータアクセスをデフォルトでロックしておき、roles.json ファイルを設定して、許可されたセッションにのみ限定的に一部を開放することです。 たとえば、制限されたアクセスをゲストセッションに対して許可する場合:

/Project/Sources/roles.json

{
"privileges": [
{
"privilege": "none",
"includes": []
}
],
"roles": [],
"permissions": {
"allowed": [
{
"applyTo": "ds",
"type": "datastore",
"read": [
"none"
],
"create": [
"none"
],
"update": [
"none"
],
"drop": [
"none"
],
"execute": [
"none"
],
"describe": [
"none"
],
"promote": [
"none"
]
},
{
"applyTo": "ds.loginAs",
"type": "method",
"execute": [
"guest"
]
},
{
"applyTo": "ds.hasPrivilege",
"type": "method",
"execute": [
"guest"
]
},
{
"applyTo": "ds.clearPrivileges",
"type": "method",
"execute": [
"guest"
]
},
{
"applyTo": "ds.isGuest",
"type": "method",
"execute": [
"guest"
]
},
{
"applyTo": "ds.getPrivileges",
"type": "method",
"execute": [
"guest"
]
},
{
"applyTo": "ds.setAllPrivileges",
"type": "method",
"execute": [
"guest"
]
},
{
"applyTo": "mySingletonClass.createID",
"type": "singletonMethod",
"execute": [
"guest"
]
}
]
},
"forceLogin": true
}