tyoshikawa1106のブログ

- Force.com Developer Blog -

SFDC:『with sharing』と『without sharing』の切り替えによるアクセス権の変化

Apexクラス内では、『with sharing』を宣言することで実行ユーザのアクセス権限のある情報のみ取得するように制御できます。システム権限で実行する場合は『without sharing』と宣言します。


複数のクラスを使用する処理で『with sharing』と『without sharing』がそれぞれ宣言された場合の挙動について確認してみます。

はじめに

検証用にName項目のみのカスタムオブジェクトを作成しました。
f:id:tyoshikawa1106:20150217221612p:plain

共有設定で非公開(private)に設定しています。これでwith sharingのときは他のユーザのレコードを取得できないようになります。
f:id:tyoshikawa1106:20150217221748p:plain


Administratorというユーザでレコードを5件作成しました。作成者であるAdministratorは検索ページでこのレコードを表示できます。
f:id:tyoshikawa1106:20150217221925p:plain


この条件でAdministratorとは別のユーザが検索処理を行う形で検証を進めていきます。

検証①:with sharing

まずはwith sharingを宣言したクラスでクエリを実行した場合です。
f:id:tyoshikawa1106:20150217222902p:plain


結果は次の通り、Administratorとは別のユーザが検索した場合、Administratorの作成したレコードは検索結果には表示されません。
f:id:tyoshikawa1106:20150217223141p:plain

検証②:without sharing

それではwith sharingをwithout sharingに変更して実行してみます。
f:id:tyoshikawa1106:20150217223325p:plain


Administratorが作成したレコードも取得できるようになりました。
f:id:tyoshikawa1106:20150217223444p:plain


ここまでは大丈夫ですね。それではクエリ実行のみ行うDaoクラスを用意してwith sharingとwithout sharingがそれぞれ宣言された場合を確認していきます。

検証③:with sharing → without sharing

まず、クエリを実行するDaoクラスを用意します。こちらはwithout sharingで宣言します。
f:id:tyoshikawa1106:20150217224349p:plain

Controller側ではwith sharingを宣言します。
f:id:tyoshikawa1106:20150217224439p:plain


これで元のクラスはwith sharing、クエリ実行クラスはwithout sharingという形になりました。この状態で実行してみた結果がこちらです。
f:id:tyoshikawa1106:20150217224609p:plain


クエリ実行を行ったクラスの権限が優先されることを確認できました。

検証④:without sharing → with sharing

さてそれでは、検証③の条件とは逆にクエリ実行を行うクラスの方をwith sharingに変更して確認してみます。

まずDaoクラスはこんな感じです。
f:id:tyoshikawa1106:20150217224844p:plain


Controller側はwithout sharingを宣言します。
f:id:tyoshikawa1106:20150217224941p:plain


クエリ実行クラスの権限が優先されるはずなのでwith sharingで実行されるはずです。結果はこちら。
f:id:tyoshikawa1106:20150217225100p:plain


予定どおりですね。このようにwith sharing / without sharingの宣言はクエリ実行を行うクラスの宣言が適用されます。


最後にもう1つのパターンを確認してみたいと思います。上の検証では、Daoクラスはstaticを宣言して呼び出しました。そうではなく、newを宣言してインスタンスを生成して呼び出した場合を確認してみます。

検証⑤:Daoクラスがstaticでない場合

Daoクラス側です。without sharingを宣言します。
f:id:tyoshikawa1106:20150217225554p:plain


Controller側です。with sharingを宣言します。
f:id:tyoshikawa1106:20150217225631p:plain


クエリ実行するクラスの宣言が適用されるはずなのでwithout sharingで実行されるはず・・。


結果です。
f:id:tyoshikawa1106:20150217225730p:plain


without sharingの権限で実行できていますね。これでクエリ実行クラスの呼び出しは、staticでもnewのときでも違いがないことが確認できました。


複数クラスでの『with sharing』と『without sharing』の切り替えはこのように適用されます。基本的には『with sharing』を宣言しておくことになると思います。例外時、例えばApexトリガーで件数の集計処理を行うようなときは、without sharingを宣言して組織内のすべてのレコードにアクセスさせる..というような使い分けを行う感じだと思います。