As promised a follow up post on my first post on Rhino Security. This post will deal with the integration of Rhino Security in ASP.NET MVC.
In our application we need to deal with different levels of security:
- Security on field level: some users cannot see certain fields
- Security on operations.
- Security on the data a user can see. e.g. a certain user can see vehicles but not the BMW's. That means that in each query that is sent to the database the BMW's need to be filters out.
For now I will focus on 1 and 2 and I hope to find some time to come back on 3 in a next post. But before we do all that we have to some preparations:
Preparations
We have created our own base Controller that derives from the System.Web.Mvc.Controller. That Controller has an attribute: Authorization. This "AuthorizationAttribute" derives from the default "ActionFilterAttribute" and first checks whether the user is authenticated and after that it checks whether the user is authorized to perform the action that is requested. That brings us to security on operations:
Security on operations
On each public action method we add an attribute "SecuredOperation" and the "AuthorizationFilter" checks whether the logged in user is authorized to perform the requested action using the "Rhino.Security.Interfaces.IAuthorizationService". That means of course that we need to add all "SecuredOperations" to Rhino.Security. Now, that is quite easy. We just loop over all action methods with the "SecuredOperation" attribute and add them to Rhino.Security using the IAuthorizationRepository. Security on operations is not enough in our case. In some cases we also need security on field level. It turns out that ASP.NET MVC makes this really easy to do
Security on field level
Extensions methods are key here. You are probably already using the "HtmlHelpers" in your application. To include security you just need to extend those and use the extended ones. You create for example a "Html.SecuredTextbox" and a "Html.SecuredActionLink". In the implementation of those you check whether the user has access to the field or operation and you deal with it accordingly. In the case of the textbox you can for example show it, show it disabled or not show it.
Conclusion
This post shows that without a lot of effort you can integrate the powers of Rhino.Security in ASP.NET MVC and of course you can do exactly the same in Castle.Monorail. I hope to find some time in the coming weeks to write about secured queries, meaning that you restrict query results based on the user rights.

10 comments:
Can you also publish the source?
I'm working on a sample application, I will publish that on Google code once it's ready.
Ayende,
I have created a sample application. You can find it here:http://code.google.com/p/winecellarmanager/source/browse/#svn/trunk/WineCellarManagerOnASPNETMVC
or with SVN:
svn checkout http://winecellarmanager.googlecode.com/svn/trunk/
hi
>
> Do we need to add tables in the rhino security schema for
> each and every entity we want to add to entity group ??? or
> the entities would be picked from application schema only
> ???? How does the rhino security interact with the entities
> present in application schema(say in sharparch . core )?
> The examples given always show a coding line as
>
> Account account =
> Repository(Account).FindFirst();
>
> User user = Repository(User).FindFirst();
> var auth =
> container.Resolve(IAuthorizationService)();
> Console.WriteLine(auth.IsAllowed(user,
> account, "/Account/Delete"));
> Console.WriteLine(auth.GetAuthorizationInformation(user,
> account, "/Account/Delete"));
>
> Now where is this "Accounts " table ? is it in application
> schema or rhino schema ? n what is the use of
> Repository(Account).FindFirst(); ???
>
> Can u pls send a demo on functionalities like adding
> entities to entity groups ,IEntityInformationextractor
> ? as the data on these things are not very
> elaborartive on the forums ?
The problem with this implementation is that as your platform increases in size you fire off a lot of requests for permissions. Especially as you implement granular object level, field level, method level, page level, feature level permissions.
What way have you handled this?
I am considering caching the available permissions and then storing the users permissions in the IIdentity as roles.
Is there any better ways to handle this that you have employed?
Ryan, we implemented caching per request and as far as I know it was enough.
You do have to think the use of Rhino Security through. Think about whether you actually need such a flexible security system. In many cases you actually want to have a task driven UI.
Bart,
Yeah the flexibility of Rhino Security is exactly what we need. We have a large enterprise SAAS product whereby roles/usersgroups and permissions are a requirement as well as page and feature level authentication.
You can check out my blog to see a dummed down implementation.
I have also been considering creating an interceptor to check for Rhino Security calls and check against a cached list of available permissions.
Hi I would love to see how you address issue number 3 where you need to filter query results by permissions.
Also is this project still maintained? I'm concerned that if I integrate it into my sys I'll be committed and if the project is dead than I may be up the creek.
Thanks,
R
@Canibal Coder, I believe you better ask put that question on the mailing list. I am not following that project anymore. The address of the mailling list should be rhino-tools-dev@googlegroups.com
Post a Comment