Dynamics CMR 4.0では、フィールドレベルのセキュリティは提供されません。今回の、[Dynamics CRM] フィールドレベルセキュリティの一実装 RetrieveMultiple メッセージ編に続いて、エンティティレコードのフォームを表示(参照)するときや、単一のエンティティレコード情報参照時に使用される Retrieve を対象にして、フィールドレベルのセキュリティを実装するサンプルを紹介します。

フィールドレベルセキュリティーにつていは、 下記リンクの 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

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

  • メールアドレスに"制限情報"という文字列を設定して出力する
  • 売上高50000以上の企業の売上高をマスク

動作確認環境

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

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

1. 実装方針

1.1 プラグインによる実装

フィールドレベルのセキュリティはプラグイン(サーバ側)で実装します。javascript などクライアント側で項目を非表示、マスクなどをしても、知識のあるユーザは情報を取得する方法ができるためです。もちろん、マスクされたデータなどのフィールドをフォームから非表示、編集できないようにしてユーザビリティを向上させることは有用だと思います。

1.2 実装ステージ

Pre Stage で項目から除外することで、フィールドレベルのセキュリティを実装することも可能ですが今回はPost Stage でメールアドレスが存在した場合に特定の文字列の設定および売上高50000以上の売上高をマスクします。これは取得結果を確認しないとセキュリティを適用できないため。つまり、ロジック処理が必要なためです。

2サンプル実装

Post Stage において、メールアドレスと、売上高がマスク条件に該当する場合は、値をマスクしています。

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>
    /// 検索 (Retrieveメッセージ)に対するフィールドレベルの
    /// セキュリティ設定の実装例
    /// 
    /// </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.Retrieve))
                {
                    if (context.Stage == 50)
                    {
                        RemoveFieldInRetrievePostStage(context);
                    }
                }
            }
        }

        #endregion

        #region Retrieveメッセージ
        /// <summary>
        /// 特定のフィールドの表示を禁止する。
        /// メールアドレスの表示を制限する。
        /// 売上高が50000以上のフィールドは値にマスクを行う。
        /// フォーム側で、javascript で非表示にするなどする。
        /// </summary>
        /// <param name="context"></param>
        public void RemoveFieldInRetrievePostStage(IPluginExecutionContext context)
        {
            if (context.PrimaryEntityName == "account")
            {
                DynamicEntity entity = context.OutputParameters.Properties[ParameterName.BusinessEntity] as DynamicEntity;
                if (entity != null)
                {
                    // E-mail アドレスは非開示
                    if (entity.Properties.Contains("emailaddress1"))
                    {
                        entity.Properties["emailaddress1"] = "制限情報";
                    }

                    if (entity.Properties.Contains("revenue"))
                    {
                        CrmMoney v = entity.Properties["revenue"] as CrmMoney;
                        if (v.Value > 50000m)
                        {
                            // 項目をブランクにする場合NULL値セット
                            // entity.Properties["revenue"] = CrmMoney.Null;
                            // 項目をマスクする場合
                            v.Value = 999999999999;
                        }
                    }
                }
               
            }
        }
        #endregion
    }
}

実行結果は次のようになります。電子メールに制限情報という文字列が設定され、、売上高がが50000より多い場合は999999999999にマスクされます。

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

サンプル実装では、Post Stage で対象とする項目があればセキュリティを適用しました。 Pre Stage で、対象とする属性が指定されていた場合、除外や例外をスローするという方法もあります。その場合は取得フィールドに AllColumns が指定された場合などの振る舞いも決めておく必要があります。

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