Пользователь @mdma немного описывает Аспектно-ориентированное программирование. Для этого вам нужно будет использовать внешнюю библиотеку (например, отличный PostSharp), потому что .NET не имеет большого количества функций AOP. Однако, .NET уже имеет механизм AOP для обеспечения безопасности на основе ролей, который может решить часть вашей проблемы. Посмотрите на следующий пример стандартного кода .NET:
[PrincipalPermission(SecurityAction.Demand, Role="HR")]
public List<Employees> GetAllEmployees()
{
// do stuff
}
PrincipalPermissionAttribute является частью пространства имен System.Security.Permissions и является частью .NET (с .NET 1.0). Я уже много лет использую его для обеспечения безопасности на основе ролей в своих веб-приложениях. Хорошая вещь об этом атрибуте заключается в том, что компилятор .NET JIT делает все плетение для вас на заднем плане, и вы даже можете определить его на уровне класса. В этом случае все члены этого типа наследуют этот атрибут и его параметры безопасности.
Конечно, у него есть свои ограничения. Второй образец кода не может быть реализован с использованием атрибута безопасности на основе ролей .NET. Я думаю, что вы не можете найти некоторые специальные проверки безопасности в этом методе или вызвать некоторую внутреннюю библиотеку безопасности.
public Order GetMyOrder(int orderId)
{
Order o = GetOrderInternal(orderId);
BusinessSecurity.ValidateOrderForCurrentUser(o);
}
Конечно, вы можете использовать АОП, но вы все равно придется написать определенный атрибут рамки, которые будут снова вызывать свой собственный уровень безопасности. Это было бы полезно только тогда, когда такой атрибут заменил бы вызовы нескольких методов, например, когда нужно было бы вводить код внутри try, catch, finally. Когда вы будете делать простой вызов метода, не будет большой разницы между одним вызовом метода или единственным атрибутом IMO.
Когда вы возвращаете коллекцию объектов и хотите, чтобы отфильтровать все объекты, для которых текущий пользователь не имеет соответствующие права, деревья выражений LINQ может пригодиться:
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;
}
}
Когда ваш O/RM поддерживает LINQ через деревья выражений (такие как NHibernate, LINQ to SQL и Entity Framework), вы можете написать такой метод безопасности один раз и применить его повсюду. Конечно, приятная вещь в том, что запрос к вашей базе данных всегда будет оптимальным. Другими словами, больше записей не будет получено, чем необходимо.
UPDATE (года):
Я использовал этот атрибут в течение длительного времени в моей базе кода, но несколько лет назад, я пришел к выводу, что атрибут на основе АОП имеет ужасные недостатки. Например, это препятствует тестируемости. Так как код безопасности сплетается с обычным кодом, вы не можете запускать обычные модульные тесты без необходимости выдавать себя за действительного пользователя. Это хрупкое и не должно вызывать беспокойства в отношении единичного теста (сам тест устройства нарушает принцип единой ответственности). Кроме того, это заставляет вас заманивать вашу базу кода этим атрибутом.
Так что вместо использования PrincipalPermissionAttribute
, я скорее применяю сквозные проблемы, такие как безопасность, путем обертывания кода с помощью decorators. Это делает мое приложение более гибким и гораздо более простым в тестировании. Я написал несколько статей об этой технике последние пару лет (например, this one и this one).
Я вижу, что вы некоторое время были на СО. Тем не менее, я предлагаю вам оставить теги ([.net/C#]) вне заголовка. Пусть они остаются в тегах. Кроме того, «Привет» и «Спасибо», если они подходят для дискуссионного форума, не подходят для сайта Q & A, такого как SO. Благодарю. –
@John ok. Спасибо за подсказки. – gsharp