with sharing、without sharing、および inherited sharing キーワードの使用
With Sharing
with sharing キーワードでは、クラスで現在のユーザの共有ルールを考慮するように指定できます。Apex コードはシステムコンテキストで実行されるため、このキーワードはクラスで明示的に設定する必要があります。システムコンテキストでは、Apex コードはすべてのオブジェクトと項目にアクセスできます。オブジェクト権限、項目レベルセキュリティ、共有ルールは現在のユーザには適用されません。この戦略により、ユーザには非表示の項目またはオブジェクトが原因でコードの実行が失敗することを避けることができます。このルールの唯一の例外は、executeAnonymous コールおよび Chatter in Apex と共に実行される Apex コードです。executeAnonymous は常に、現在のユーザのフル権限を用いて実行されます。executeAnonymous の詳細は、「匿名ブロック」を参照してください。
現在のユーザに適用されている共有ルールを強制実行するには、クラスの宣言時に with sharing キーワードを使用します。次に例を示します。
1public with sharing class sharingClass {
2
3// Code here
4
5}Without Sharing
現在のユーザに適用されている共有ルールを強制実行されないようにするには、クラスの宣言時に without sharing キーワードを使用します。たとえば、クラスが with sharing を使用して宣言された別のクラスからコールされた場合、共有ルールの強制実行を明示的にオフにできます。
1public without sharing class noSharing {
2
3// Code here
4
5}with sharing および without sharing キーワードに関する実装の詳細
- メソッドがコールされるクラスの共有設定ではなく、メソッドが定義されているクラスの共有設定が適用されます。たとえば、with sharing が宣言されたクラス内に定義されているメソッドが、without sharing が宣言されたクラスでコールされる場合、そのメソッドの実行では共有ルールが適用されます。
- with sharing も without sharing もクラスで宣言されていない場合、現在の共有ルールが有効となります。そのため、クラスが別のクラスから共有ルールを取得する場合を除き、共有ルールは強制実行されません。たとえば、共有が強制実行されている別のクラスからクラスがコールされた場合、コールされたクラスにも共有が強制実行されます。
- 内部クラスと外部クラスは、どちらも with sharing として宣言できます。共有設定は、初期化コード、コンストラクタ、メソッドなどクラスに含まれているすべてのコードに適用されます。
- 内部クラスはそのコンテナクラスから共有設定を継承しません。
- クラスが別のクラスを拡張または実装している場合、親クラスからこの設定が継承されます。
Inherited Sharing
共有宣言のない Apex は、デフォルトでは安全ではありません。実行時に with sharing または without sharing モードで実行可能な Apex クラスの設計は高度な手法です。このような手法では、特定の共有宣言が誤って省略されている場所を特定することは困難な場合があります。明示的な inherited sharing 宣言は意図が明確なため、省略された宣言による曖昧さやセキュリティ分析ツールの誤検出を回避できます。
- Aura コンポーネントコントローラ
- Visualforce コントローラ
- Apex REST サービス
- その他の Apex トランザクションへの開始ポイント
inherited sharing のある Apex クラスと省略された共有宣言のある Apex クラスには、明確な違いがあります。クラスが Apex トランザクションの開始点として使用されている場合、省略された共有宣言は without sharing として実行されます。一方、inherited sharing ではデフォルトで確実に with sharing として実行されます。inherited sharing として宣言されたクラスが without sharing として実行されるのは、すでに確立されている without sharing コンテキストから明示的にコールされた場合のみです。
例
1public inherited sharing class InheritedSharingClass{
2 public List<Contact> getAllTheSecrets(){
3 return [SELECT Name FROM Contact];
4 }
5}1<apex:page controller="InheritedSharingClass">
2 <apex:repeat value="{!allTheSecrets}" var="record">
3 {!record.Name}
4 </apex:repeat>
5</apex:page>