Domanda

Sto lavorando su un po 'di sicurezza basata sul ruolo per la nostra app e essenzialmente voglio fare Verison MVC personalizzati AuthorizeAttribute - ma solo nel livello della logica aziendale, dove non ci colleghiamo a MVC.

Ho guardato PrincipalPermissionAttribute Ma sembra che non abbia un modo per personalizzarlo perché è sigillato. Voglio solo creare una versione personalizzata in cui posso verificare l'iscrizione qualunque di un elenco di ruoli senza utilizzare più attributi e definire anche dove cercare l'appartenenza al ruolo.

C'è qualcosa di simile in .NET che mi manca? O qualcuno ha qualche idea su come farlo senza reimplementare l'autorizeattribute/ruolo di RoleProvider di ASP.NET/ecc.?

MODIFICARE

Attualmente ho una versione imperativa in esecuzione, ma preferirei avere una versione dichiarativa-attributo, in quanto è più facile vederla al di sopra del metodo/classe.

In questo momento ho quanto segue in una classe di base astratta per il mio livello aziendale:

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

Mi piace essere in grado di usare Roles.Administrator ecc. Perché i nomi dei ruolo sono orribili (basati sul gruppo di Active Directory ...), quindi stavo pensando di avvolgere quei dettagli nel costruttore di un attributo personalizzato che posso semplicemente superare le classi/metodi.

GetAccountRoles è solo una facciata rispetto a una proprietà iniettabile per il fornitore di ruolo, che posso impostare per utilizzare AD o una versione di test che utilizza il database.

Potrei sottoclasse Attribute, ma non sono sicuro di come avrebbe dato il via al controllo di sicurezza.

È stato utile?

Soluzione

È possibile creare un nuovo attributo che utilizza il PrincipalPermission esistente se ciò sarebbe sufficiente per le tue esigenze. Se l'implementazione imperativa esistente utilizza PrincipalPermission, allora dovrebbe essere il caso. Tuttavia, se la tua versione imperativa fa qualcos'altro, potrebbe essere necessario prendere in considerazione l'implementazione sia di un'autorizzazione personalizzata che di un attributo corrispondente. Se non sei sicuro che sia necessario, forse potresti condividere alcuni dettagli sul tuo attuale approccio imperativo ...


Dopo l'aggiornamento della domanda ...

In realtà è possibile utilizzare "qualsiasi" logica con PrincipalPermission, sebbene richieda un sindacato di più casi, che non è particolarmente pratico con cui lavorare in un attributo. Questo rende molto più ragionevole creare un attributo personalizzato, che potrebbe assomigliare a quanto segue:

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

Sfortunatamente, non è possibile utilizzare array negli attributi di sicurezza, quindi l'elenco dei ruolo deve essere rappresentato come una stringa. per esempio:

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

Potresti usarlo con le tue costanti tramite concatenazione del tempo di progettazione. per esempio:

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

Per quanto riguarda il tuo fornitore di ruolo personalizzato, il luogo appropriato per utilizzarlo è nel principale principale, non l'autorizzazione o l'attributo. Ad esempio, se stai attualmente utilizzando un PRINCAL GENERIC, potresti sostituirlo con un capitale personalizzato che utilizza il tuo fornitore di ruolo personalizzato per recuperare i ruoli dell'identità target.

Altri suggerimenti

Potresti derivare la tua codeaccessicurityTribute e implementare la tua logica attorno al thread.CurrentPrincipal (http://msdn.microsoft.com/en-us/library/system.security.permissions.codeaccesssecurityattribute.aspx).

In sostanza, vorresti verificare allowedRoles.Any(r => Thread.CurrentPrincipal.IsInRole(r))

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top