Frage

Ich arbeite an einer rollenbasierten Sicherheit für unsere App und möchte im Wesentlichen maßgeschneiderte Verison MVCs durchführen AuthorizeAttribute - aber nur in der Geschäftslogikschicht, in der wir nicht mit MVC verlinken.

Ich habe mich angesehen PrincipalPermissionAttribute Aber es scheint keine Möglichkeit, es so anzupassen, wie es versiegelt ist. Ich möchte nur eine benutzerdefinierte Version erstellen, in der ich nach einer Mitgliedschaft suchen kann irgendein einer Liste von Rollen ohne mehrere Attribute zu verwenden und auch zu definieren, wo nach der Rolle der Rolle gesucht werden soll.

Gibt es so etwas in .NET, das mir fehlt? Oder hat jemand einen Einblick, wie man dies tut, ohne die AutorizeAttribute/roleProvider/etc von ASP.NET zu reproduzieren?

BEARBEITEN

Ich habe derzeit eine imperative Version, aber ich hätte lieber eine deklarativ-attribute-Version, da es einfacher ist, sie über die Methode/Klasse zu sehen.

Im Moment habe ich Folgendes in einer abstrakten Basisklasse für meine Geschäftsschicht:

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.");
}

Ich mag es zu benutzen Roles.Administrator usw. Da die Rollennamen schrecklich sind (Active Directory -Gruppenbasiert ...), dachte ich darüber nach, diese Details in den Konstruktor eines benutzerdefinierten Attributs zu wickeln, das ich einfach über Klassen/Methoden aufnehmen kann.

GetAccountRoles ist nur eine Fassade über eine injizierbare Rollen-Provider-Eigenschaft, die ich entweder AD oder einer Testversion verwenden kann, die die Datenbank verwendet.

Ich könnte unterklassen Attribute, aber nicht sicher, wie es den Sicherheitscheck starten würde.

War es hilfreich?

Lösung

Sie können ein neues Attribut erstellen, das die vorhandene Prinzipie verwendet, wenn dies für Ihre Bedürfnisse ausreicht. Wenn Ihre vorhandene Implementierung die Prinzipie verwendet, sollte dies der Fall sein. Wenn Ihre imperative Version jedoch etwas anderes tut, müssen Sie möglicherweise sowohl eine benutzerdefinierte Berechtigung als auch ein entsprechendes Attribut implementieren. Wenn Sie nicht sicher sind, ob dies notwendig ist, können Sie möglicherweise einige Details zu Ihrem aktuellen Imperativansatz teilen ...


Nach Frage -Update ...

Es ist tatsächlich möglich, "jede" Logik mit PrincipalPermission zu verwenden, obwohl die Vereinigung mehrerer Instanzen erforderlich ist, was in einem Attribut nicht besonders praktisch ist. Dies macht es viel vernünftiger, ein benutzerdefiniertes Attribut zu erstellen, das ungefähr wie folgt aussehen könnte:

[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;
    }
}

Leider können Sie Arrays in Sicherheitsattributen nicht verwenden, daher muss die Rollenliste als Zeichenfolge dargestellt werden. z.B:

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

Sie können es mit Ihren Konstanten über die Verkettung von Design-Zeit verwenden. z.B:

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

Was Ihren benutzerdefinierten Rollenanbieter betrifft, ist der geeignete Ort für die Verwendung im Thread -Principal, nicht in der Berechtigung oder zum Attribut. Wenn Sie beispielsweise einen GenericPrincipal verwenden, können Sie ihn durch einen benutzerdefinierten Auftraggeber ersetzen, der Ihren benutzerdefinierten Rollenanbieter verwendet, um die Rollen der Zielidentität abzurufen.

Andere Tipps

Sie können Ihre eigene CodeAccessSecurityAttribute ableiten und Ihre Logik rund um den Thread implementieren.

Im Wesentlichen möchten Sie überprüfen allowedRoles.Any(r => Thread.CurrentPrincipal.IsInRole(r))

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top