2

アプリのロールベースのセキュリティに取り組んでおり、基本的にカスタマイズされたバージョンの MVC を実行したいと考えていますAuthorizeAttributeが、MVC にリンクしていないビジネス ロジック レイヤーでのみ実行します。

見ましたPrincipalPermissionAttributeが、封印されているのでカスタマイズする方法はないようです。複数の属性を使用せずにロールのリストのメンバーシップをチェックできるカスタム バージョンを作成し、ロール メンバーシップを探す場所を定義したいだけです。

私が行方不明になっている.Netにこのようなものはありますか? または、ASP.Net の AuthorizeAttribute/RoleProvider/etc を再実装せずにこれを行う方法について洞察を持っている人はいますか?

編集

私は現在、命令型バージョンを実行していますが、メソッド/クラスの上にある方が見やすいので、宣言型属性バージョンを使用したいと考えています。

現在、ビジネス層の抽象基本クラスに次のものがあります。

protected void EnsureEditorLevelAccess()
{
    var allowedRoles = new[]
                            {
                                Roles.Administrator,
                                Roles.Editor,
                            };

    var roles = GetAccountRoles(GetCurrentUsername());

    if (roles.Any(role => allowedRoles.Contains(role)))
    {
        return;
    }

    throw new SecurityException("You do not have sufficient privileges for this operation.");
}

ロール名がひどいので(Active Directoryグループベース...)などを使用できるのが好きなRoles.Administratorので、クラス/メソッドの上に配置できるカスタム属性のコンストラクターにそれらの詳細をラップすることを考えていました.

GetAccountRolesこれは、AD またはデータベースを使用するテスト バージョンのいずれかを使用するように設定できます。

をサブクラス化できAttributeましたが、セキュリティ チェックを開始する方法がわかりません。

4

2 に答える 2

5

必要に応じて、既存の PrincipalPermission を使用する新しい属性を作成できます。既存の命令型実装で PrincipalPermission を使用している場合は、これが当てはまるはずです。ただし、命令型バージョンが何か他のことを行う場合は、カスタム アクセス許可と対応する属性の両方を実装することを検討する必要がある場合があります。これが必要かどうかわからない場合は、現在の必須のアプローチに関する詳細を共有できます...


質問の更新後...

実際には PrincipalPermission で「任意の」ロジックを使用できますが、複数のインスタンスを結合する必要があり、属性で操作するのは特に実用的ではありません。これにより、次のようなカスタム属性を作成する方がはるかに合理的になります。

[Serializable]
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
public sealed class AnyRolePermissionAttribute : CodeAccessSecurityAttribute
{
    public AnyRolePermissionAttribute(SecurityAction action)
        : base(action)
    {
    }

    public string Roles { get; set; }

    public override IPermission CreatePermission()
    {
        IList<string> roles = (this.Roles ?? string.Empty).Split(',', ';')
                                .Select(s => s.Trim())
                                .Where(s => s.Length > 0)
                                .Distinct()
                                .ToList();

        IPermission result;
        if (roles.Count == 0)
        {
            result = new PrincipalPermission(null, null, true);
        }
        else
        {
            result = new PrincipalPermission(null, roles[0]);
            for (int i = 1; i < roles.Count; i++)
            {
                result = result.Union(new PrincipalPermission(null, roles[i]));
            }
        }

        return result;
    }
}

残念ながら、セキュリティ属性では配列を使用できないため、ロール リストは文字列として表す必要があります。例えば:

[AnyRolePermission(SecurityAction.Demand, Roles = "Foo, Bar")]

設計時の連結を介して定数と一緒に使用できます。例えば:

[AnyRolePermission(SecurityAction.Demand, Roles = Roles.Administrator + ", " + Roles.Editor)]

カスタム ロール プロバイダーに関しては、それを使用する適切な場所は、アクセス許可や属性ではなく、スレッド プリンシパルです。たとえば、現在 GenericPrincipal を使用している場合は、カスタム ロール プロバイダーを使用してターゲット ID のロールを取得するカスタム プリンシパルに置き換えることができます。

于 2011-12-02T15:35:11.153 に答える