Question

Je travaille sur une certaine sécurité basée sur les rôles pour notre application et je veux essentiellement ne mesure verison de AuthorizeAttribute de MVC - mais seulement à la couche logique métier, où nous ne sommes pas lien vers MVC.

Je l'ai regardé PrincipalPermissionAttribute mais il semble qu'il n'a pas une façon de le personnaliser comme il est scellé. Je veux juste créer une version personnalisée où je peux vérifier l'appartenance à tout d'une liste de rôles sans utiliser plusieurs attributs, et aussi définir où chercher les membres du rôle.

Y at-il quelque chose comme ça en .Net que je suis absent? Ou est-ce que quelqu'un a une idée sur la façon de le faire sans réimplémentant AuthorizeAttribute de ASP.Net / RoleProvider / etc?

EDIT

J'ai actuellement une version impérative en cours d'exécution, mais je préfère avoir une version déclarative attribut, car il est plus facile de le voir ci-dessus la méthode / classe.

En ce moment, je suit dans une classe de base abstraite pour ma couche métier:

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

Je aime pouvoir utiliser Roles.Administrator etc parce que les noms de rôle sont hideux (groupe Active Directory base ...), donc je pensais à envelopper ces détails dans le constructeur d'un attribut personnalisé que je peux juste plop sur le dessus des classes / méthodes.

GetAccountRoles est juste une façade sur une propriété injectable fournisseur de rôle, que je peux mettre à utiliser soit AD ou une version de test qui utilise la base de données.

Je ne sous-classe Attribute, mais ne sais pas comment il le coup d'envoi du contrôle de sécurité.

Était-ce utile?

La solution

Vous pouvez créer un nouvel attribut qui utilise le PrincipalPermission existant si ce serait suffisant pour vos besoins. Si votre application utilise impératif existant PrincipalPermission, alors cela devrait être le cas. Toutefois, si votre version impérative fait quelque chose d'autre, vous devrez peut-être envisager d'appliquer à la fois une autorisation personnalisée et un attribut correspondant. Si vous n'êtes pas sûr que cela est nécessaire, peut-être que vous pourriez partager quelques détails au sujet de votre approche actuelle impératif ...


Après la mise à jour de question ...

Il est en fait possible d'utiliser « toute » logique avec PrincipalPermission, même si elle nécessite unioning d'instances multiples, ce qui est pas particulièrement pratique pour travailler dans un attribut. Cela le rend beaucoup plus raisonnable de créer un attribut personnalisé, ce qui pourrait ressembler à ce qui suit:

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

Malheureusement, vous ne pouvez pas utiliser des tableaux dans les attributs de sécurité, de sorte que la liste des rôles doit être représentée comme une chaîne. par exemple:.

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

Vous pouvez l'utiliser avec vos constantes par concaténation temps de conception. par exemple:.

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

En ce qui concerne votre fournisseur de rôle personnalisé, l'endroit approprié pour l'utiliser est le principal fil, pas l'autorisation ou l'attribut. Par exemple, si vous utilisez actuellement un GenericPrincipal, vous pouvez le remplacer par un directeur personnalisé qui utilise votre fournisseur de rôle personnalisé pour récupérer le rôle de l'identité cible.

Autres conseils

Vous pouvez obtenir votre propre CodeAccessSecurityAttribute et mettre en œuvre votre logique autour du Thread.CurrentPrincipal (http://msdn.microsoft.com/en-us/library/system.security.permissions.codeaccesssecurityattribute.aspx).

essentiellement, vous voulez vérifier allowedRoles.Any(r => Thread.CurrentPrincipal.IsInRole(r))

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top