with sharingキーワードとwithout sharingキーワード
Apexはデフォルトでシステムモードで動作するので、全オブジェクトに対して全レコードの編集が可能です。
そのため、例えば、ユーザがVisualforceページでレコードを検索する場合、ユーザが参照権限を持たないレコードについても、検索できてしまいます。
ユーザが参照可能なレコードのみを検索できるようにするには、Apexクラスにwith sharingキーワードを付与します。
これによって、ユーザに適用されているレコードレベルの共有ルールを強制実行することができます(ユーザモードでの動作)。
public with sharing class SharingClass {
}
ここで注意しなくてはならないのは、with sharingキーワードを付与しても、オブジェクトのCRUD権限、項目のアクセス権限は、システムモードのままということです。ユーザがアクセスできないはずのオブジェクトや項目にアクセスできてしまいます。
オブジェクトのCRUD権限、項目のアクセス権限は、Apexでは制御できないので、開発者が、ユーザから隠されているデータを公開しないように注意してApexコードを書く必要があります。
逆に、ユーザに適用されている共有ルールを強制実行されないようにするには、without sharingキーワードを付与します。
public without sharing class NoSharingClass {
}
with sharingキーワードもwithout sharingキーワードも付与しない場合は、呼び出し元のApexクラスの設定が有効となります。
例えば、with sharingキーワードが付与されたApexクラスから、キーワードなしのApexクラスを呼び出した場合、ユーザに適用されている共有ルールが強制実行されます。呼び出し位置が最上位レベルの場合(最初に呼ばれるApexクラスの場合)は、システムモードでの動作となります。
動作モードを表にまとめるとこうなります。
呼び出し位置 | キーワード | ||
---|---|---|---|
なし | without sharing | with sharing | |
最上位レベル | システムモード | システムモード | ユーザモード |
最上位レベル以外 | 呼び出し元のモードと同じ | システムモード | ユーザモード |
ちなみに、トリガはシステムモードの動作となりますが(トリガにはキーワードを付けることができない)、トリガ内部でwith sharingキーワード付きのApexクラスを呼び出すことで、ユーザモードでの動作となります。
また、匿名ブロックは、ユーザモードでの動作となります。
>tamaさん
とてもわかりやすいですね。
Salesforceのマニュアルにも同様の記述がありますが、
sharingキーワードがない場合とwithout sharingキーワードを使用した場合ではどこに違いがあるのか、とまどったことがありました。
Force.com OneAppを使用する際、with sharingを使用して、アクセスするオブジェクトを少なくする等の工夫が必要となるので、このようにまとまった形で公開してくれるのはとても助かります。
投稿: ys | 2010年11月10日 (水) 10:26
>ysさん
コメントありがとうございます!
私自身、with/without sharingキーワードの挙動で戸惑って、詳しく調べたことがあったので、まとめてみました。
これからも、役立つ情報をお届けしていきたいと思ってますので、是非よろしくお願いします。
投稿: tama | 2010年11月15日 (月) 18:52