前回の[Dynamics CRM] フィールドレベルセキュリティ の一実装 Createメッセージ編に続いて、最後にエンティティレコードの更新 Update メッセージに対してフィールドレベルセキュリティを実装してみます。

フィールドレベルセキュリティーにつていは、 下記リンクの Dynamics CRM 4.0 における、フィールドレベルセキュリティのホワイトペーパーを参考にしています。

Security and Authentication in Microsoft Dynamics CRM: Field-level Security in Microsoft Dynamics CRM: Options and Constraints
http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=471f8670-47b3-4525-b25d-c11a6774615c

対象は取引先企業エンティティとし、次の機能を提供します。

  • 作成する取引先企業にメールアドレスが設定しようとすると例外(InvalidPluginExecutionException)をスローする
  • 売上高50000以上の取引先企業を設定する場合は例外(InvalidPluginExecutionException)をスローする

動作確認環境

  • Dynamics CRM 4.0 Update Rollup 8
  • .NET 3.5, Visual Studio 2008

.NET3.0 以上で使用されるusing を除去すれば、.NET 2.0 でも動作すると思います。

1. 実装方針

1.1 プラグインによる実装

フィールドレベルのセキュリティはプラグイン(サーバ側)で実装します。javascript などクライアント側で項目を非表示、マスクなどをして権限外の処理を行わせないようにすることも有用ですが、Webサービスから作成することもできるので、プラグインとして実装する必要があります。

1.2 実装ステージ

Updateメッセージの場合は、更新が完了する前に検証を行う必要があるため、Pre Stage で項目の内容をチェックしてフィールドレベルセキュリティを実装します。

2サンプル実装

Update メッセージの Pre Stage において、メールアドレスが含まれる場合、売上高が50000以上の場合は例外を発生させています。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Crm.Sdk;
using Microsoft.Crm.Sdk.Query;
using System.Xml;
using System.Xml.Linq;

namespace FieldlevelSecurityPlugin
{
    /// <summary>
    /// 更新 (Updateメッセージ)に対するフィールドレベルの
    /// セキュリティ設定の実装例
    /// 
    /// </summary>
    public class FieldLevelPlugin : IPlugin
    {

        #region IPlugin メンバ
        /// <summary>
        /// プラグインのエントリ
        /// </summary>
        /// <param name="context"></param>
        public void Execute(IPluginExecutionContext context)
        {
            if (context.CallerOrigin is ApplicationOrigin)
            {
                if (context.MessageName.Equals(MessageName.Update))
                {
                    if (context.Stage == 10)
                    {
                        CheckInUpdatePreStage(context);
                    }
                }
            }
        }

        #endregion

        #region Updateメッセージ
        /// <summary>
        /// 特定のフィールドの更新を禁止する
        /// メールアドレスの更新や50000以上の売上げ高のフィールドを更新を禁止
        /// </summary>
        /// <param name="context"></param>
        public void CheckInUpdatePreStage(IPluginExecutionContext context)
        {
            if (context.PrimaryEntityName == "account")
            {
                DynamicEntity entity = context.InputParameters[ParameterName.Target] as DynamicEntity;
                if (entity.Properties.Contains("emailaddress1"))
                {
                    // 黙って更新をさせない場合は Remove する
                    //entity.Properties.Remove("emailaddress1");
                    throw new InvalidPluginExecutionException("メールアドレスは更新できません");
                }
                if (entity.Properties.Contains("revenue"))
                {
                    DynamicEntity preEntity = context.PreEntityImages.Properties["Target"] as DynamicEntity;
                    CrmMoney m = preEntity.Properties["revenue"] as CrmMoney;
                    if (m.Value > 50000)
                    {
                        throw new InvalidPluginExecutionException("このデータの売上げ高を権限がありません");
                    }
                }
            }
        }
        #endregion
    }
}

メールアドレスを設定して保存するとエラーダイアログが表示されるようになります。

売上高に50000以上を設定して保存するとエラーダイアログが表示されます。

3. UpdateメッセージにたいするField Level Security のまとめ

サンプル実装では、Pre Stage で対象とする項目があればセキュリティを適用するようにしています。

各メッセージごとにフィールドレベルのセキュリティの実装例を掲載してきました。実際には、検索、更新、作成、削除など考慮したセキュリティーの考慮漏れのない実装が必要となります。フィールドレベルセキュリティに対応する必要がある場合は、要件をつめて限られた範囲でのみ実装するようにしたほうがよいと考えています。

説明は以上です。誤り、指摘点などありましたらご連絡ください。