I am curious how others are handling admin views and controller actions.
Most examples will put the controller action Create, which may require admin permissions, in the same controller with actions that are public available. Is this wise, and are you using a PrincipalPermissionAttribute or checking the permissions
of the user in the action?
[ControllerAction]
[PrincipalPermission(SecurityAction.Demand, Role="Admin")]
public void Create()
{
// ...
}
I am also curious how one is managing the views. Are the admin views getting mixed in the same folder with all the other public views? If so, is there some sort of naming convention? I can see where things start to get a little cluttered when doing this
and I am having problems managing views unless I prefix the view with "Admin".
I haven't done much with access security yet, the only app I have that uses it implemented security using standard web.config url security (location elements).
I removed all the administrative actions from the controller and moved to a different controller like "ProductsAdminController" and routed all the urls under an "admin" virtual directory:
I made all my admin controllers inherit from a common base, which checks that the controller can only be accessed via the above route:
public class AdminController : Controller
{
protected override bool OnPreAction(string actionName, System.Reflection.MethodInfo methodInfo)
{
if(!ControllerContext.RouteData.Route.Url.StartsWith("admin/"))
throw new HttpException(403, "Forbidden");
return base.OnPreAction(actionName, methodInfo);
}
}
Then I could secure that url in the web.config using a location tag.
I'll be the first to admit that this approach seems a little too brittle. I'd prefer a solutions that disconnects my routes from the controllers. I haven't thought of the attribute you used. I'm also curious about what other folks are doing.
Conceptually, I take more of a AOP type approach. To me, security does not dictate how I organize my controller actions and views. It's a separate concern that lays on top of my structure and compliments it. I don't partition my site based on security needs
(for the most part). for example, I don't make the distinction between rules that say only administrator can create vs. logged in users can view. if they work on the same entity, the actions (and the views) should be grouped together. I find that much easier
to track.
Thanks for the feedback. I have been looking into that structure as well and appreciate the thorough samples you have provided.
You could add the PrincipalPermissionAttribute on the AdminController Class. I assume you could also just check for user permissions in OnPreAction. Both would allow you to uncouple the route from the controller, because all you are really concerned about
is user permissions and not the route of the request.
I wish they had a sample application that showed best practices. It would save us so much guess work.
Out of curiosity, won't the route of "admin/[controller]/[action]/[id]" by default go to the ProductsController as opposed to a ProductsAdminController assuming your route looks like:
admin/products/delete/1
which is more of an admin function?
How do you get admin/products/delete/1 and other admin functions to a ProductsAdminController as opposed to a ProductsController? An ICustomControllerFactory?
I use a fairly simple approach in implementation. Usually with a SecurityGuard service that contains all my security checks, which will throw SecurityException if it fails. then the first thing in a function would be a call out to say SecurityGuard.DemandAdminRole()
or SecurityGuard.DemandEntityOwner() whatever it maybe. You can also do decorators, or something really fancy that does aop. I decided to go with the simple approach. But the point I'm making is that, I don't let this type of crosscutting concerns dictate
how I break down my controllers. Instead I group the actions base on the entity they act on. I find it the best way to keep controllers organized. (It's also the RESTful way)
It's scary you posted this, I was about to do the same. In the postback asp.net, I did more of what Shinakuma does, have a base security class that does all the security checks and throws a security error if somethings not right. It worked well, especially
having a nice central place to add in more security checks if needed.
Shinakuma, do you have any examples you could share of how you do it in an MVC application?
Dave Hayden
Member
26 Points
19 Posts
How to Handle Admin Views and Controller Actions
Dec 26, 2007 02:35 PM|LINK
I am curious how others are handling admin views and controller actions.
Most examples will put the controller action Create, which may require admin permissions, in the same controller with actions that are public available. Is this wise, and are you using a PrincipalPermissionAttribute or checking the permissions of the user in the action?
[ControllerAction] [PrincipalPermission(SecurityAction.Demand, Role="Admin")] public void Create() { // ... }I am also curious how one is managing the views. Are the admin views getting mixed in the same folder with all the other public views? If so, is there some sort of naming convention? I can see where things start to get a little cluttered when doing this and I am having problems managing views unless I prefix the view with "Admin".
Best Regards,
Dave
sergiopereir...
Member
227 Points
61 Posts
Re: How to Handle Admin Views and Controller Actions
Dec 26, 2007 04:57 PM|LINK
I haven't done much with access security yet, the only app I have that uses it implemented security using standard web.config url security (location elements).
I removed all the administrative actions from the controller and moved to a different controller like "ProductsAdminController" and routed all the urls under an "admin" virtual directory:
RouteTable.Routes.Add(new Route { Url = "admin/[controller]/[action]/[id]", Defaults = new { action = "Index", id = (string)null }, RouteHandler = typeof(MvcRouteHandler) });I made all my admin controllers inherit from a common base, which checks that the controller can only be accessed via the above route:
Then I could secure that url in the web.config using a location tag.
I'll be the first to admit that this approach seems a little too brittle. I'd prefer a solutions that disconnects my routes from the controllers. I haven't thought of the attribute you used. I'm also curious about what other folks are doing.
Sergio Pereira
http://devlicio.us/blogs/sergio_pereira/
shinakuma
Member
378 Points
92 Posts
Re: How to Handle Admin Views and Controller Actions
Dec 26, 2007 05:39 PM|LINK
Conceptually, I take more of a AOP type approach. To me, security does not dictate how I organize my controller actions and views. It's a separate concern that lays on top of my structure and compliments it. I don't partition my site based on security needs (for the most part). for example, I don't make the distinction between rules that say only administrator can create vs. logged in users can view. if they work on the same entity, the actions (and the views) should be grouped together. I find that much easier to track.
sergiopereir...
Member
227 Points
61 Posts
Re: How to Handle Admin Views and Controller Actions
Dec 26, 2007 05:57 PM|LINK
But, in concrete terms, what is that you do?
Sergio Pereira
http://devlicio.us/blogs/sergio_pereira/
hhariri
Member
176 Points
70 Posts
Re: How to Handle Admin Views and Controller Actions
Dec 26, 2007 06:20 PM|LINK
+1
I'm pretty much taking the same approach Sergio is, but am also interested to know what you mean.
http://hadihariri.com
http://twitter.com/hhariri
Dave Hayden
Member
26 Points
19 Posts
Re: How to Handle Admin Views and Controller Actions
Dec 26, 2007 08:28 PM|LINK
Sergio,
Thanks for the feedback. I have been looking into that structure as well and appreciate the thorough samples you have provided.
You could add the PrincipalPermissionAttribute on the AdminController Class. I assume you could also just check for user permissions in OnPreAction. Both would allow you to uncouple the route from the controller, because all you are really concerned about is user permissions and not the route of the request.
I wish they had a sample application that showed best practices. It would save us so much guess work.
Regards,
Dave
Dave Hayden
Member
26 Points
19 Posts
Re: How to Handle Admin Views and Controller Actions
Dec 26, 2007 08:39 PM|LINK
Sergio,
Out of curiosity, won't the route of "admin/[controller]/[action]/[id]" by default go to the ProductsController as opposed to a ProductsAdminController assuming your route looks like:
admin/products/delete/1
which is more of an admin function?
How do you get admin/products/delete/1 and other admin functions to a ProductsAdminController as opposed to a ProductsController? An ICustomControllerFactory?
Regards,
Dave
shinakuma
Member
378 Points
92 Posts
Re: How to Handle Admin Views and Controller Actions
Dec 26, 2007 08:45 PM|LINK
I use a fairly simple approach in implementation. Usually with a SecurityGuard service that contains all my security checks, which will throw SecurityException if it fails. then the first thing in a function would be a call out to say SecurityGuard.DemandAdminRole() or SecurityGuard.DemandEntityOwner() whatever it maybe. You can also do decorators, or something really fancy that does aop. I decided to go with the simple approach. But the point I'm making is that, I don't let this type of crosscutting concerns dictate how I break down my controllers. Instead I group the actions base on the entity they act on. I find it the best way to keep controllers organized. (It's also the RESTful way)
sergiopereir...
Member
227 Points
61 Posts
Re: How to Handle Admin Views and Controller Actions
Dec 26, 2007 09:47 PM|LINK
There's a ProductsAdmin controller defined like public class ProductsAdminController : AdminController { ... } so the URL is a little different:
admin/ProductsAdmin/delete/123
The regular ProductsController, in this case, does not have a Delete() action.
I guess that, if you want that to be automatic, you could use a custom RouteHandler for that route and alter the controller name on the fly:
public class AdminRouteHandler : IRouteHandler { public IHttpHandler GetHttpHandler(RequestContext context) { MvcHandler h = new MvcHandler(); string controller = context.RouteData.Values["controller"] as string; context.RouteData.Values["controller"] = controller + "Admin"; h.RequestContext = context; return h; } } //And change the route to: RouteTable.Routes.Add(new Route { Url = "admin/[controller]/[action]/[id]", Defaults = new { action = "Index", id = (string)null }, RouteHandler = typeof(AdminRouteHandler)/* <== CHANGED!!!*/ });Sergio Pereira
http://devlicio.us/blogs/sergio_pereira/
ChadThiele
Participant
983 Points
274 Posts
Re: How to Handle Admin Views and Controller Actions
Dec 26, 2007 09:48 PM|LINK
It's scary you posted this, I was about to do the same. In the postback asp.net, I did more of what Shinakuma does, have a base security class that does all the security checks and throws a security error if somethings not right. It worked well, especially having a nice central place to add in more security checks if needed.
Shinakuma, do you have any examples you could share of how you do it in an MVC application?
Thanks!