Asp.net MVC membership design
Some Background to begin:
I've implemented a custom MembershipProvider that validates a user from my service layer called "WebMemberShipProvider"
Currently I have a service called "MembershipService", this service implements the interface IMembershipService on the service layer. this MemberShipService queries the dal, and validates a user based on username/password
I've also created a custom AuthorizeAttribute named "AuthorizeOwnerAttribute" and this is where I'm having design issues.
For each controller I have a dependency on a Service. eg. UsersController takes a IUserService in it's constructor.
How can I call AuthorizeAttribute on an ActionResult where the current logged in user and the user being edited have the same "StudioId". Note: I want to use AuthorizeAttribute with multiple controllers, not just "UserController"
So my questions to you are:
- What should I do to store the current authenticated user's "StudioId", as this will be used across multiple controllers.
- How should I pass authentication down to the service layer, because I want to validate that the requests are valid in the service and data access layers, not just on the client. (If this is advisable, I'm just assuming that validation on the client only is enough if I want to re-use the BLL and DAL later on in a stand-alone application)
Technologies used: - LINQ to SQL via the Repository pattern - ASP.NET MVC Preview 2
Any recommendations or code examples would be 开发者_开发问答very welcomed.
I basically did my security mostly at the controller level for something like this. I made a decision not to pass things down too far down the chain in order to find out whether or not a person had access to it or if I did I would just make sure IPrincipal.IsInRole() would be enough to satisfy it.
Now I did something else that feels somewhat hackier. I needed to make sure that people that were registered and had this piece assigned to them were the only ones able to access it from this section.
So I created an attribute filter that works much like this:
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var thingToView = filterContext.ActionParameters[_thingToView] as thingToView ;
var registration = filterContext.ActionParameters[_registration] as Registration;
if (!registration.CanSeeThing(thingToView))
{
throw new RegistrationCannotViewThing(registration, thingToView);
}
base.OnActionExecuting(filterContext);
}
Now the thing that felt somewhat hacky in this implementation is that I did this on my controller method:
[AuthFilter(ThingToView ="thingToView", Registration="registration")
public ActionResult Method(Thing thingToView, Registration registration)
{
....
}
The actual parameter assignments occurred in the model binder. The security happens through the filter which checks the parameters passed to the method. I then reused this filter in a lot of places.
I did something similar with a model binder to a Scott Hanselman post here: http://www.hanselman.com/blog/IPrincipalUserModelBinderInASPNETMVCForEasierTesting.aspx in order to pass what user is calling a method.
I suppose you can use the example blog post above in order to get your user object to your controller method in order to pass it to your service layer.
精彩评论