Multi User App with MVC3, ASP.NET Membership - User Authentication/ Data Separation -
i'm building simple multi-user (multi-tenant?) app asp.net mvc3 , ef4, 1 database, 1 code base, users access app using same url. once user logged in should have access data, i'm using default asp.net membership provider , have added ‘userid’ guid field on each of data tables. don't want user have access user b’s data have been adding following every action on controllers.
public actionresult editstatus(int id) { if (!request.isauthenticated) return redirecttoaction("index", "home"); var status = sservice.getstatusbyid(id); // check if logged in user has access status if (status.userid != getuserid()) return redirecttoaction("index", "home"); . . . } private guid getuserid() { if (membership.getuser() != null) { membershipuser member = membership.getuser(); guid id = new guid(member.provideruserkey.tostring()); return id; } return guid.empty; }
this repetition feeling wrong , there must more elegant way of ensuring users can't access each other's data – missing?
what missing?
a custom model binder:
public class statusmodelbinder : defaultmodelbinder { public override object bindmodel(controllercontext controllercontext, modelbindingcontext bindingcontext) { // fetch id routedata var id = controllercontext.routedata.values["id"] string; // todo: use constructor injection pass service here var status = sservice.getstatusbyid(id); // compare whether id passed in request belongs // logged in user if (status.userid != getuserid()) { throw new httpexception(403, "forbidden"); } return status; } private guid getuserid() { if (membership.getuser() != null) { membershipuser member = membership.getuser(); guid id = new guid(member.provideruserkey.tostring()); return id; } return guid.empty; } }
and register model binder in application_start
:
// use constructor injection pass repository model binder modelbinders.binders.add(typeof(status), new statusmodelbinder());
and finally
// authorize attribute ensures user authenticated. // if want redirect /home/index in original // example if user not authenticated write custom // authorize attribute , job there [authorize] public actionresult editstatus(status status) { // if got far means user has access resource // todo: status , return view ... }
conclusion: we've put controller on diet way controllers should :-)
Comments
Post a Comment