User @ 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)的一部分。我已經使用它多年來已經在我的web應用程序中實現基於角色的安全性。關於這個屬性的好處在於,.NET JIT編譯器可以在後臺爲你編織所有內容,甚至可以在類級別上定義它。在這種情況下,該類型的所有成員都將繼承該屬性及其安全設置。
當然它有其侷限性。您的第二個代碼示例不能使用基於.NET角色的安全屬性實現。我認爲你不能真正圍繞這種方法進行一些自定義安全檢查,或者調用一些內部安全庫。
public Order GetMyOrder(int orderId)
{
Order o = GetOrderInternal(orderId);
BusinessSecurity.ValidateOrderForCurrentUser(o);
}
當然你也可以使用一個AOP框架,但你仍然會寫,這將再次撥打您自己的安全層的框架的具體屬性。只有當這樣一個屬性可以代替多個方法調用時,這纔會有用,例如當必須將代碼放入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通過表達式樹(例如NHibernate,LINQ to SQL和Entity Framework)支持LINQ,您可以編寫一次這樣的安全方法並將其應用到任何地方。當然,關於這一點的好處是,對數據庫的查詢總是最優的。換句話說,沒有更多的記錄將被檢索超過需要。
UPDATE(年後):
我用這個屬性在我的代碼基礎很長一段時間,但幾年後,我來到了這個屬性基於AOP有可怕的缺點的結論。例如,它阻礙了可測試性。由於安全代碼是用普通代碼編織的,因此無法運行正常的單元測試而無需模擬有效的用戶。這是脆弱的,不應該成爲單元測試的考慮因素(單元測試本身違反單一職責原則)。除此之外,它強制你用這個屬性拋棄你的代碼庫。
因此,我寧願用decorators來包裝代碼,而不是使用PrincipalPermissionAttribute
來代替安全性。這使得我的應用程序更加靈活並且更容易測試。在過去的幾年中,我已經寫了幾篇關於這種技術的文章(例如this one和this one)。
我看到你已經在SO一段時間了。不過,我會建議您將標籤([.net/c#])留在標題之外。讓他們留在標籤中。此外,「嗨」和「謝謝」雖然適合討論論壇,但並不適用於SO等問答站點。謝謝。 – 2010-06-10 04:28:59
@John好的。感謝提示。 – gsharp 2010-06-10 06:30:25