Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>User @mdma describes a bit about Aspect Oriented Programming. For this you will need to use an external library (such as the great PostSharp), because .NET doesn’t have much AOP functionality. However, .NET already has a AOP mechanism for role based security, that can solve part of your problem. Look at the following example of standard .NET code:</p> <pre><code>[PrincipalPermission(SecurityAction.Demand, Role="HR")] public List&lt;Employees&gt; GetAllEmployees() { // do stuff } </code></pre> <p>The <a href="https://msdn.microsoft.com/en-us/library/system.security.permissions.principalpermissionattribute.aspx" rel="nofollow noreferrer">PrincipalPermissionAttribute</a> is part of the System.Security.Permissions namespace and is part of .NET (since .NET 1.0). I’ve been using it for years already to implement role based security in my web applications. Nice thing about this attribute is that the .NET JIT compiler does all the weaving for you on the background and you can even define it on a class level. In that case all members of that type will inherit that attribute and its security settings.</p> <p>Of course it has its limitations. Your second code sample can't be implemented using the .NET role based security attribute. I think you can’t really come around some custom security checks in this method, or calling some internal security library.</p> <pre><code>public Order GetMyOrder(int orderId) { Order o = GetOrderInternal(orderId); BusinessSecurity.ValidateOrderForCurrentUser(o); } </code></pre> <p>Of course you can use an AOP framework, but you would still have to write an framework specific attribute that will again call your own security layer. This would only get useful when such an attribute would replace multiple method calls, for instance when having to put code inside try,catch,finally statements. When you would be doing a simple method call, there wouldn’t be much difference between a single method call or a single attribute IMO.</p> <p>When you are returning a collection of objects and want to filter out all objects for which the current user doesn't have the proper rights, LINQ expression trees can come in handy:</p> <pre><code>public Order[] GetAllOrders() { IQueryable orders = GetAllOrdersInternal(); orders = BusinessSecurity.ApplySecurityOnOrders(orders); return orders.ToArray(); } static class BusinessSecurity { public static IQueryable&lt;Order&gt; ApplySecurityOnOrders( IQueryable&lt;Order&gt; 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; } } </code></pre> <p>When your O/RM supports LINQ through expression trees (such as NHibernate, LINQ to SQL and Entity Framework) you can write such a security method once and apply it everywhere. Of course the nice thing about this is, that the query to your database will always be optimal. In other words, no more records will be retrieved than needed.</p> <p><strong>UPDATE (years later):</strong></p> <p>I used this attribute for a long time in my code base, but several years back, I came to the conclusion that attribute based AOP has terrible downsides. For instance, it hinders testability. Since security code is weaved with normal code, you can't run normal unit tests without having to impersonate a valid user. This is brittle and should not be a concern of the unit test (the unit test itself violates the Single Responsibility Principle). Besides that, it forces you to litter your code base with that attribute.</p> <p>So instead of using the <code>PrincipalPermissionAttribute</code>, I rather apply cross-cutting concerns like security by wrapping code with <a href="https://en.wikipedia.org/wiki/Decorator_pattern" rel="nofollow noreferrer">decorators</a>. This makes my application much more flexible and much easier to test. I've written several articles about this technique the last couple of years (for instance <a href="https://cuttingedge.it/blogs/steven/pivot/entry.php?id=91" rel="nofollow noreferrer">this one</a> and <a href="https://cuttingedge.it/blogs/steven/pivot/entry.php?id=92" rel="nofollow noreferrer">this one</a>).</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload