Apex クラスの保護

デフォルトでは、Apex はシステムモードで実行されます。つまり、非常に上位の権限で実行され、あたかもユーザがほとんどの権限を持っていてすべての項目レベルおよびオブジェクトレベルのアクセス権が付与されているように動作します。これらのセキュリティレイヤが Salesforce UI のように適用されないため、適用するためのコードを記述する必要があります。そうしないと、通常は Salesforce UI ではユーザに表示されない機密データがコンポーネントによって公開されてしまう可能性があります。

Salesforce のレコードを処理する場合は、共有ルール、CRUD、および項目レベルセキュリティをユーザに代わって扱ってくれる Lightning Data Service の使用をお勧めします。「データガイドライン」を参照してください。

認証済みユーザまたはゲストユーザは、ユーザのプロファイルまたは割り当てられた権限セットで Apex クラスへのアクセスが許可されている場合にのみ、@AuraEnabled Apex メソッドにアクセスできます。

Apex クラスへのユーザプロファイルまたは権限セットのアクセス権の設定についての詳細は、『Apex 開発者ガイド』の「クラスのセキュリティ」を参照してください。

クラスを宣言するときには、with sharing を指定して、コンポーネントが Apex コントローラを使用するときに共有ルールを適用することをお勧めします。

with sharing または without sharing を明示的に設定しない、あるいは inherited sharing を使用して定義された @AuraEnabled Apex クラスは、デフォルトまたは暗黙的な値として with sharing を使用します。ただし、with sharing または without sharing のどちらも明示的に指定されていない Apex クラスでは、Apex クラスが実行されているコンテキストから値が継承されます。したがって、このいずれかのキーワードを設定したクラスによって、明示的な共有動作を指定していないクラスが呼び出された場合、そのクラスは呼び出し元のクラスの共有動作を使用して動作します。クラスで共有ルールが適用されるようにするには、with sharing を設定します。

with sharing キーワードを使用すると、レコードレベルのセキュリティが適用されます。オブジェクトレベルおよび項目レベルのセキュリティは適用されません。オブジェクトレベルおよび項目レベルのセキュリティは、Apex クラスで手動で別々に適用する必要があります。

Apex コード内でオブジェクトレベルおよび項目レベルの権限を適用するには、いくつかの代替方法があります。

WITH SECURITY_ENFORCED を使用した最も簡単な適用

オブジェクトレベルおよび項目レベルの権限を適用するには、Apex コード内の SOQL SELECT クエリ (サブクエリとクロスオブジェクトリレーションを含む) で WITH SECURITY_ENFORCED 句を使用します。

WITH SECURITY_ENFORCED 句は、セキュアなコードの開発経験が少ししかない場合や、権限エラーのグレースフルデグラデーションがアプリケーションで不要な場合に最適です。

次の例では、セキュアでないメソッド get_UNSAFE_Expenses() を含むカスタム Expense オブジェクトの項目が照会されます。このクラスは使用しないでください。

次の例では、セキュアなメソッド getExpenses() が使用されます。このメソッドは、WITH SECURITY_ENFORCED 句を使用して、オブジェクトレベルの権限と項目レベルの権限を適用します。このクラスは UnsafeExpenseController の代わりに使用します。

詳細は、『Apex 開発者ガイド』を参照してください。

stripInaccessible() を使用したグレースフルデグラデーション

権限エラーのグレースフルデグラデーションを可能にするには、stripInaccessible() メソッドを使用して項目レベルおよびオブジェクトレベルのデータ保護を適用します。このメソッドではクエリおよびサブクエリの結果からユーザがアクセスできない項目およびリレーション項目を除外します。必要に応じて、項目が除外されたかどうかを検出し、カスタムエラーメッセージを含む AuraHandledException を発生させることができます。

このメソッドを使用すると、DML 操作の前にアクセス不可の sObject 項目を削除して例外を回避したり、信頼できないソースからデシリアライズされた sObject をサニタイズしたりすることもできます。

次の例では、WITH SECURITY_ENFORCED SOQL 句の代わりに stripInaccessible() を使用するように ExpenseController が更新されます。結果は同じになりますが、stripInaccessible() では、WITH SECURITY_ENFORCED の使用時にアクセス違反が発生した場合、失敗する代わりに、グレースフルデグラデーションを行うことができます。

詳細や例については、『Apex 開発者ガイド』を参照してください。

DescribeSObjectResult メソッドと DescribeFieldResult メソッドを使用した従来のコード

WITH SECURITY_ENFORCED 句と stripInaccessible() メソッドが使用できるようになるまでは、オブジェクトと項目の権限を適用する唯一の方法は、Schema.DescribeSObjectResult メソッドと Schema.DescribeFieldResult メソッドをコールしてユーザのアクセス権限を確認することでした。そして、ユーザに必要な権限がある場合には特定の DML 操作またはクエリを実行します。

たとえば、Schema.DescribeSObjectResultisAccessibleisCreateable、または isUpdateable メソッドをコールすると、現在のユーザーが sObject に対して、それぞれ参照アクセス権、作成アクセス権、または更新アクセス権を持っているかどうかを確認できます。同様に、Schema.DescribeFieldResult が公開しているアクセス制御メソッドをコールすると、現在のユーザーが項目に対して参照アクセス権、作成アクセス権、または更新アクセス権を持っているかどうかを確認できます。

次の例では、Describe Result メソッドが使用されています。この方法では、定型のコード行がさらに多く必要になるため、代わりに WITH SECURITY_ENFORCED 句または stripInaccessible() メソッドを使用することをお勧めします。

関連トピック