Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC Protecting User Based Data Security

I am starting to dabble with ASP.Net MVC. One question I have is on best practices for protecting user data. For example in the scenario of Sales people, they should only be able to view their own data.

e.g.

SalesData/Edit/14

It is very easy to change the "14" to view other data which they may/or may not have access to.

At this point, I am thinking in my controllers to check for who is logged in, and checking if they have access to the "id" that is getting requested. The problem I see with this, is that this will be application wide, and I am looking for best practices on how to approach this. Should I be looking at CustomControllers? Filters? or what? Any articles/references for how to tackle this would be appreciated.

like image 602
zzz Avatar asked Jul 23 '26 13:07

zzz


2 Answers

Set up your methods for retrieving data from your database repository in such a way that you can pass the UserID of the currently logged in person as a parameter. You can then use a permissions table to filter the data to only that data for which the user has access.

The permissions table would have two fields: UserID and ContentID. Once this is set up, it's fairly straightforward to set up CRUD screens so that someone with administrative privileges can set content permissions.

like image 144
Robert Harvey Avatar answered Jul 26 '26 06:07

Robert Harvey


The problem I see with this, is that this will be application wide,

Then you need common service that handles it. Suprisingly, I would call it IAuthorisationService.

and I am looking for best practices on how to approach this. Should I be looking at CustomControllers? Filters? or what?

Whichever way you choose you should use common IAuthorisationService above.
From my experience I can tell that it is easier to inject the service into controller and use it on every action:

/* Interfaces */
public interface IAuthorisationService {
    bool CanEdit(YourItem item);
}

public interface ICurrentUserProvider {
    YourUserEntity GetCurrentUser();
}

/* Implementations */
public class HttpUserProvider : ICurrentUserProvider {
    public YourUserEntity GetCurrentUser() {
        return HttpContext.Current.User.Principal as YourUserEntity;
    }
}

public calss RolesAuthorisationService : IAuthorisationService {
    ICurrentUserProvider userProvider
    public RolesAuthorisationService(ICurrentUserProvider userProvider) {
        this.userProvider = userProvider;
    }

    public bool CanEdit(YourItem item) {
        var u = userProvider.GetCurrentUser();
        if (u == null)
            return false;
        return item.Owner == u && u.IsInRole("EditYourItem");
    }
}

/* Controller */

public class MyController: Controller {
    IAuthorisationService authorisation;

    public MyController(IAuthorisationService authorisation) {
        this.authorisation = authorisation;
    }

    public ActionResult Edit(int id) {
        var item = GetTheItembyIdSomehow();
        if (!authorisation.CanEdit(item))
            return new HttpUnauthorizedResult();

        // Can do this
    }
}

Then you can use ControllerFactory to inject the required dependencies automatically into the controllers:

class DependencyInjectionContainer : WindsorContainer {
    public DependencyInjectionContainer() {
        RegisterDependencies();
    }

    private void RegisterDependencies() {

        // Services
        Register(
            AllTypes.Of<IDiscoverableService>()
                .FromAssembly(typeof(IDiscoverableService).Assembly)
                .Configure(c => c.LifeStyle.Transient)
                .WithService.FromInterface()
            );

        // Controllers
        Register(
            AllTypes.Of<IController>()
                .FromAssembly(typeof(DependencyInjectionContainer).Assembly)
                .Configure(c => c.LifeStyle.Transient)
            );
    }
}

class WindsorControllerFactory : DefaultControllerFactory, IDisposable {
    private readonly IWindsorContainer container;

    public WindsorControllerFactory() {
        container = new DependencyInjectionContainer();
    }

    protected override IController GetControllerInstance(Type controllerType) {
        if (controllerType == null)
            return base.GetControllerInstance(controllerType);
        return (IController) container.Resolve(controllerType);
    }

    public void Dispose() {
        container.Dispose();
    }
}
like image 27
Dmytrii Nagirniak Avatar answered Jul 26 '26 05:07

Dmytrii Nagirniak



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!