L'utilisateur @mdma décrit un peu à propos de la programmation orientée aspect. Pour cela, vous devrez utiliser une bibliothèque externe (telle que la bonne PostSharp), car .NET n'a pas beaucoup de fonctionnalités AOP. Toutefois, .NET dispose déjà d'un mécanisme AOP pour la sécurité basée sur les rôles, qui peut résoudre une partie de votre problème. Regardez l'exemple suivant de code standard .NET:
[PrincipalPermission(SecurityAction.Demand, Role="HR")]
public List<Employees> GetAllEmployees()
{
// do stuff
}
Le PrincipalPermissionAttribute fait partie de l'espace de noms System.Security.Permissions et fait partie de .NET (depuis la version 1.0 .NET). Je l'utilise depuis des années déjà pour implémenter la sécurité basée sur les rôles dans mes applications web. Une bonne chose à propos de cet attribut est que le compilateur .NET JIT fait tout le tissage pour vous en arrière-plan et vous pouvez même le définir au niveau de la classe. Dans ce cas, tous les membres de ce type hériteront de cet attribut et de ses paramètres de sécurité.
Bien sûr, il a ses limites. Votre deuxième exemple de code ne peut pas être implémenté à l'aide de l'attribut de sécurité basé sur le rôle .NET. Je pense que vous ne pouvez pas vraiment contourner certains contrôles de sécurité personnalisés dans cette méthode, ou appelez une bibliothèque de sécurité interne.
public Order GetMyOrder(int orderId)
{
Order o = GetOrderInternal(orderId);
BusinessSecurity.ValidateOrderForCurrentUser(o);
}
Bien sûr, vous pouvez utiliser un cadre de l'AOP, mais vous auriez encore d'écrire un cadre attribut spécifique qui appellera à nouveau votre propre couche de sécurité. Cela ne serait utile que si un tel attribut remplaçait plusieurs appels de méthode, par exemple lorsqu'il fallait mettre du code à l'intérieur de try, catch, finally statements. Lorsque vous effectuez un appel de méthode simple, il n'y aurait pas beaucoup de différence entre un seul appel de méthode ou un seul attribut IMO.
Lorsque vous retournez une collection d'objets et que vous voulez filtrer tous les objets pour lesquels l'utilisateur actuel ne dispose pas des droits appropriés, les arbres d'expression LINQ peuvent être utiles:
public Order[] GetAllOrders()
{
IQueryable orders = GetAllOrdersInternal();
orders = BusinessSecurity.ApplySecurityOnOrders(orders);
return orders.ToArray();
}
static class BusinessSecurity
{
public static IQueryable<Order> ApplySecurityOnOrders(
IQueryable<Order> orders)
{
var user = Membership.GetCurrentUser();
if (user.IsInRole("Administrator"))
{
return orders;
}
return
from order in orders
where order.Customer.User.Name == user.Name
select order;
}
}
Lorsque votre O/RM prend en charge LINQ via les arborescences d'expression (telles que NHibernate, LINQ to SQL et Entity Framework). Vous pouvez écrire une telle méthode de sécurité une seule fois et l'appliquer partout. Bien sûr, la bonne chose à ce sujet est que la requête à votre base de données sera toujours optimale. En d'autres termes, plus d'enregistrements seront récupérés que nécessaire.
MISE À JOUR (années plus tard):
J'ai utilisé cet attribut depuis longtemps dans ma base de code, mais plusieurs années, je suis venu à la conclusion que l'attribut base AOP a de terribles inconvénients. Par exemple, il empêche la testabilité. Puisque le code de sécurité est tissé avec du code normal, vous ne pouvez pas exécuter des tests unitaires normaux sans avoir à emprunter l'identité d'un utilisateur valide. Ceci est fragile et ne devrait pas être une préoccupation du test unitaire (le test unitaire viole le Principe de Responsabilité Unique). En plus de cela, il vous oblige à jeter votre base de code avec cet attribut.
Donc, au lieu d'utiliser le PrincipalPermissionAttribute
, j'applique plutôt les préoccupations transversales comme la sécurité en enveloppant le code avec decorators. Cela rend mon application beaucoup plus flexible et beaucoup plus facile à tester. J'ai écrit plusieurs articles sur cette technique au cours des dernières années (par exemple this one et this one).
Je vois que vous avez été sur SO pendant un certain temps. Cependant, je vous suggère de laisser les balises ([.net/C#]) hors du titre. Laissez-les rester dans les tags. En outre, "Bonjour" et "Merci", bien que appropriés pour un forum de discussion, ne sont pas appropriés pour un site Q & A comme SO. Merci. –
@John ok. Merci pour les conseils. – gsharp