進行状況の追跡を始めよう
Trailhead のホーム
Trailhead のホーム

CRUD および FLS 違反の防止

学習の目的

この単元を完了すると、次のことができるようになります。

  • Visualforce での CRUD および FLS 違反を防止する。
  • Apex での CRUD および FLS 違反を防止する。

CRUD および FLS 違反から保護する

前の単元で見てきたように、カスタムアプリケーションでのデータの表示方法と処理方法によっては、許可されていないユーザが、本来ならばアクセスできないデータにアクセスしたり、変更したりする可能性があります。幸い、プラットフォームでは許可されていないアクセスを簡単に防ぐことができます。

DescribeSObjectResult クラスには、ユーザのアクセスレベルを検証して、データがうっかり公開または変更されることを防ぐために使用できるヘルパー関数が複数含まれています。

  • IsCreateable()
  • IsAccessible()
  • IsUpdateable()
  • IsDeleteable()

では、これらの各関数がどのような動作をするかを見てみましょう。

isCreateable()

コードがレコードをデータベースに挿入する前に、ログインユーザが項目に対する「編集」権限と、オブジェクトに対する「作成」権限の両方を持っていることを確認する必要があります。両方の権限は、特定の項目が isCreateable() であるかどうかをチェックして確認できます。

ユーザが、[金額] 項目が $500 の商談を作成する必要があるとします。関数をコールしているユーザが、商談および商談金額を作成する権限を持っていることを確認するには、Apex コードでチェックを実行し、ユーザが Opportunity.Amount に対する isCreateable() 権限を持っているかどうかを確認します。

  if (!Schema.sObjectType.Opportunity.fields.Amount.isCreateable()){
    ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR,'Error: Insufficient Access'));
    return null;
  }
  Opportunity o = new Opportunity(Amount=500);
  insert o;
  

例では、ユーザがオブジェクトではなく、項目を作成できることを明示的に検証しています。幸い、項目へのアクセス権を確認すると、ユーザがオブジェクトに対する作成アクセス権を持っていることを暗黙的に確認することにもなります。したがってこの場合、FLS を確認すると、無料で CRUD 検証も行われます。

isAccessible()

コードがオブジェクトから項目を取得する前に、その項目が isAccessible() であることを確認して、ログインユーザが項目へのアクセス権限を持っていることを確認します。

ユーザが商談の [期待収益] 項目にアクセスする必要があるとします。Apex コードで、ユーザが Opportunity.ExpectedRevenue に対する isAccessible 権限を持っているかどうかを確認します。

    // Check if the user has read access on the Opportunity.ExpectedRevenue field
    if (!Schema.sObjectType.Opportunity.fields.ExpectedRevenue.isAccessible()){
      ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR,'Error: Insufficient Access'));
      return null;
    }
    Opportunity [] myList = [SELECT ExpectedRevenue FROM Opportunity LIMIT 1000];
  

isUpdateable()

同様に、コードがレコードを更新する前に、ログインユーザが項目とオブジェクトに対する「編集」権限の両方を持っていることを確認する必要があります。両方の権限は、特定の項目が isUpdateable() であるかどうかチェックして確認できます。

ユーザが商談を更新してフェーズを「成立」とマークする必要があるとします。Apex コードで、ユーザが Opportunity.StageName に対する isUpdateable() 権限を持っているかどうかを確認します。

      //Let’s assume we have fetched opportunity “o” from a SOQL query
      if (!Schema.sObjectType.Opportunity.fields.StageName.isUpdateable()){
        ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR,'Error: Insufficient Access'));
        return null;
      }
      o.StageName=’Closed Won’;
      update o;
      

isCreateable の例で確認したように、ここではオブジェクト項目に対する FLS を明示的に確認し、同時に CRUD の暗黙的な検証を行います。

では、組織で実際に試してみましょう。

  1. Kingdom Management 開発者組織にログインします。
  2. 右側にあるアプリケーションピッカーから [CRUD/FLS & Sharing (CRUD/FLS & 共有)] を選択します。
  3. [isUpdateable Demo (isUpdateable デモ)] タブをクリックします。

    isUpdateable Demo アプリケーションのスクリーンショット

    このアプリケーションには、王国内の 2 つの城の間で行われた馬上槍試合トーナメントのスコアボードが表示されます。リストには、トーナメントの各参加者とその順位が表示されます。ランキングは編集可能ですが、適切な権限を持つユーザのみがランクの編集を行うようにする必要があります。

    このアプリケーションには、アプリケーションを使用するさまざまなユーザをシミュレーションできるドロップダウンがあります。

  4. [Read ONLY Access to the Jousters object (Jousters オブジェクトへの参照のみアクセス権)] を持つユーザを選択します。

    このユーザに適用された権限セットは次のとおりです。
    スコア項目への参照のみアクセス権を示すスクリーンショット

    ご覧のとおり、ユーザはオブジェクトに対する参照アクセス権と編集アクセス権を持っていますが、ランク項目に対する編集アクセス権は持っていません。

  5. アプリケーションで、Vinay the Chain Breaker のランクを 1 に変更して第 1 位にします。
  6. [更新] をクリックします。

    ログインユーザにはランク項目への参照アクセス権しかないはずですが、それでもランクを更新できたようです。
    適切な権限なしでランク設定が更新されたことを示すスクリーンショット

    これを修正しましょう。

  7. [Return to User Selection (ユーザ選択に戻る)] をクリックして、システム管理ユーザに戻ります。
  8. ページ下部にある [Apex Controller (Apex コントローラ)] リンクをクリックします。

    次に、アプリケーションの更新を制御するコードを示します。
              public PageReference updateRequest(){
                try{
                  update jousters;
                  init();
                }
                catch(DmlException ex){
                  ApexPages.addMessages(ex);
                }
                return null;
              }
              

    リンクがクリックされると、updateRequest 関数によってすべてのスコアボードレコードが更新されます。このアクションは、ユーザに必要な FLS 権限があってもなくても実行されます。これは、コードに明示的な認証チェック (isUpdateable()) を含めて修正できます。

  9. 画面上部の [編集] をクリックして、updateRequest Apex 関数を変更します。

    アプリケーションが update をコールする前に、次の if ステートメントを追加します。
    if (Schema.sObjectType.Jouster__c.fields.Rank__c.isUpdateable())

    変更した関数は次のようになります。
              public PageReference updateRequest(){
                try{
                  if(Schema.sObjectType.Jouster__c.fields.Rank__c.isUpdateable()){
                    update jousters;
                  }
                  else {
                    ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR,'Error: User is unauthorized to modify the scoreboard rankings'));
                  }
                  init();
                }
                catch(DmlException ex){
                  ApexPages.addMessages(ex);
                }
                return null;
              }
              
  10. [保存] をクリックして、[isUpdateable Demo (isUpdateable デモ)] タブに戻ります。
  11. [User with Only Read Access to Jousters (馬上槍競技者への参照アクセス権のみを持つユーザ)] を選択します。
  12. 参加者のランクを変更し、[更新] リンクをクリックします。

    アプリケーションが脆弱ではなくなったことを示す更新された isUpdateable Demo アプリケーションのスクリーンショット

    今回はエラーメッセージが表示され、レコードは更新されません。完璧です。

isDeleteable()

最後に、「削除」アクセス制限を適用するために、コードでデータベースの削除操作が実行される前に、isDeleteable() 関数を使用します。 

      if (!Lead.sObjectType.getDescribe().isDeleteable()){
        delete l;
        return null;
      }
    

更新、作成、アクセスとは異なり、削除の場合は明示的に CRUD チェックのみを実行し、ユーザがオブジェクトを削除できることを確認します。SOQL でレコードをすべて削除し、項目は削除しないので、ユーザのオブジェクトへの CRUD アクセス権のみを確認する必要があります。

リソース