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.
Related
I have several services that are currently highly decoupled. Now I have to extend them and they need to depend to access each other.
Let's say I have 4 services: EmailService, HouseService, UserService, PriceService. Each user has an email address and each user belongs to a house.
I want to send an email to each user about the price of the house that they are connected to. So in the EmailService I have SendEmailToAddress(string email, string text), in PriceService I have GetHousePrice(int id), in HouseService I have GetUsersInHouse(int id) and in UserService I have GetEmailOfUser(int id).
What would be the best approach to send an email to all the users from the HouseController? Should I just init all the services in the controller action and call each one in order or should I use the Mediator pattern? If I should use it, it would probably contain only one method so it seems a bit of an overkill. Also if I use it everywhere should I create different mediators for each service connection or should it be only one class that has all my services as private properties and then in the methods use only the once I need for a specific action? If I go with the Mediator pattern should I use it in every controller or should I stick with the bare services where they don't need to interact together (e.g. if I only need a list of houses I think it's probably best to just get them directly from the service object instead of the Mediator)?
Given that your services aren't actually needing to communicate with each other, you just need to call various methods on each and use the return values to complete a higher level task, I don't think the Mediator pattern is appropriate here.
For example, its not like you need the HouseService to manipulate the state of objects managed by the PriceService...you just need data from the PriceService that the HouseService provides input for:
var houseId = houseService.GetIdOfHouse(someCriteria);
var price = priceService.GetPriceOfHouse(houseId);
Instead, I think what you need to implement is the Facade pattern, which will:
Provide a unified interface to a set of interfaces in a subsystem. Façade defines a higher-level interface that makes the subsystem easier to use.
Good example of Facade pattern can be found on the dofactory.com site:
http://www.dofactory.com/net/facade-design-pattern
Here's what I would consider doing:
public class NotificationFacade
{
private IPriceService _priceService;
private IHouseService _houseService;
private IUserService _userService;
private IEmailService _emailService;
public NotificationFacade(IPriceService priceService, IHouseService houseService, IUserService userService, IEmailService emailService)
{
_priceService = priceService;
_houseService = houseService;
_userService = userService;
_emailSerice = emailSerice;
}
public void NotifyUsersAboutPriceForHouse(int houseId)
{
var price = _priceService.GetHousePrice(houseId);
var users = _houseService.GetUsersInHouse(houseId);
foreach(var user in users)
{
var emailAddress = _userService.GetEmailOfUser(user);
_emailService.SendEmailToAddress(emailAddress, "Your House Price is:" + price);
}
}
}
In your controller:
public HouseController
{
private NotificationFacade _notificationFacade;
public HouseController(NotificationFacade notificationFacade)
{
_notificationFacade = notificationFacade;
}
public void SomeActionMethod(int houseId)
{
_notificationFacade.NotifyUsersAboutPriceForHouse(houseId);
}
}
The dependencies should be resolved using Dependency Injection with a container such as Unity, Ninject, StructureMap or something similar...
You could create a workflow service that contains the actual logic to look up the information and send the mail using the existing services.
This service is then called from your HouseController. You could use the service directly as a class library or expose it as a WCF service; but it depends on your requirements.
This way your entity services remain loosely coupled, and all of your cross-service logic is in a dedicated component.
As I was looking for best practices since past couple of days in ASP.Net MVC and I concluded that our services should contain all business logic ( using repositories of different domain models) and expose public methods that are accessible by controller.
In your case you should create a new service and put the whole logic of calculation and sending email in a method of that service. So that your service will work like a black box. Other developers (who work on your project) don't need to know that how thing are managed in that method. All they need to know is to call that method with required parameter and handle response.
Just create HouseServiceFacade that contains the services you need. In this facade you can put all methods for the controller.
Facts:
I'm using webapi on my application.
My application is a multi-customer application.
Most of my business logic is identical but I do have some differences between some customers.
The example I'll give here is a basic "login" example. I have some more critical places in my system where I need an extra controller(I know that I can perform multiple workarounds with this simple login controller).
Let's assume I have a login controller that looks something like this:
public class LoginController
{
public LoginResponse Post(LoginRequest request)
{
// call ICustomer service to authenticate and return a response
}
}
Now I use IOC for my services. So each customer can typically use a different service and authenticate differently, but what happens when I need to return different data back to the client(per customer)?
I can use ILoginResponse & ILoginRequest and achieve this using IOC, but I still would like to add another LoginController(with the same name so my client's will call api\Login) and gain another level of abstraction.
So my next thought was keep the same controller name and split each customers controller into a different DLLs.
So I would have something like this:
CommonControllers.dll
Customer1Controllers.dll
Customer2Controllers.dll
But how can I do the mapping here?
I'll have an interface that looks like:
public interface ILoginControllerInterface<S,T>
{
S Post(T model);
}
And implementations that look like:
CommonControllers.dll
public class LoginController : ILoginControllerInterface<LoginResponse,LoginRequest>
{
public LoginResponse Post(LoginRequest request)
{
// call ICustomer service to authenticate and return a response
}
}
Customer1Controllers.dll
public class LoginController : ILoginControllerInterface<LoginCusomterResponse,LoginCustomerRequest>
{
public LoginCusomterResponse Post(LoginCustomerRequest request)
{
// call ICustomer service to authenticate and return a response
}
}
But how can I tell my resolver to resolve the "correct" LoginController?
I'm using Unityas my IOC container and my services are registered via configuration.
I'd like a place to register my controllers.
I've overridden the default web-api resolver using my own resolver:
GlobalConfiguration.Configuration.DependencyResolver = resolver;
I'm using my customer resolve to resolve basically everything in my application.
I'm not using a controller factory. Since my resolver resolves my controllers and performs DI for me.
Bottom line:
If I get a request to api/login, how can I resolve the correct controller?
Lets say for customer1 I'd like to get the Customer1Controller.dll version and for customer2 I'd like to get the CommonControllers.dll.
I want this to be via a configuration so I can gain flexibility.
BTW:
If there is a better practice to do these kind of things I'd be more than glad to here about it.
Thanks!!!
In our ASP.NET MVC project we are using Ninject to resolve our dependencies needed by the controllers.
One of these dependencies is the current user HttpContext.Current.User.Identity. If the user is authenticated we would like to instantiate a user object and several services which relies on it. But we would like to do this not manually but let ninject inject these instances to the controller.
So we get into trouble now, since a url can be located without being authenticated of course. Then ninject tries to resolve the instances before asp.net can redirect to the login page.
I can think of the solution, that we configure ninject do just inject when user is authenticated:
kernel.Bind<User>().ToMethod(GetUser).When(context => HttpContext.Current.User.Identity.IsAuthenticated).InRequestScope();
The problem here is that even if the user is not authenticated ninject instantiates a default object, so my services crashes or needs to check the instance anyhow.
Null checks would me much more acceptable but I wouldn't like to activate AllowNullInjection setting of Ninject.
So my question is whats the best practise for doing such conditional things?
Are there Ninject features I could use in these cases or shouldn't I inject these dependencies anyway?
I assume you are talking about a situation where a non-authenticated user could try to navigate to a page that normally requires authentication, but without first going through the login process. Ninject would then be unable to inject the current user object into the controller because it's not yet known and will throw an exception.
I can see 2 options:
The first option is instead of injecting the current user, create a factory or provider that retrieves the current user details and inject this instead. The controller can then call the provider to get the current user and if the user is unavailable you can redirect to the login page.
public OrdersController(IUserProvider userProvider)
{
this.userProvider = userProvider
}
public void DoSomething()
{
var user = this.userProvider.GetCurrentUser();
if (user == null)
RedirectToLogin();
// continue doing something
}
public class UserProvider : IUserProvider
{
public User GetCurrentUser() { ... }
}
The problem with this option is that you'll need to do this potentially in many controllers (it's a "cross cutting concern") and you don't want to have to repeat the code that does the redirect over and over. Instead, a second option would be to use the Decorator design pattern to create an interceptor that checks for logged in users before forwarding on to the real controller.
The way I've done something similar in the past is using the Ninject Interception Extension to create an attribute that marks which controllers require authentication, like this (bit psuedo-codey):
public class AuthenticationInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
bool authenticated = // ... get the current user ...
if (authenticated)
invocation.Proceed();
else
RedirectToLoginPage(); // however you want to do this
}
}
public class RequiresAuthenticationAttribute : InterceptAttribute
{
public override IInterceptor CreateInterceptor(IProxyRequest request)
{
return request.Context.Kernel.Get<AuthenticationInterceptor>();
}
}
[RequiresAuthentication]
public class OrdersController : IOrdersController
{
// assume you've already been authenticated
}
The interceptor will automatically be created whenever a class that's decorated with RequiresAuthentication is created and the current user credentials will be checked. If they are invalid, the request will be forwarded to the login page, otherwise it will continue as normal. This one interceptor can then be written and tested once whilst being used in many places without duplicating code.
Just as a simple auth and non auth answer that some may find useful.
kernel.Bind<ICustomUser>()
.To<User>()
.When(ctx => HttpContext.Current.User.Identity.IsAuthenticated)
.InRequestScope();
kernel.Bind<ICustomUser>()
.To<Guest>()
.When(ctx => !HttpContext.Current.User.Identity.IsAuthenticated)
.InRequestScope();
Otherwise anything more complex Adam Rodgers awnser is better :)
I have seen many posts of how to setup a session per request in Asp.Net MVC by using ActionFilter or by a DI package to inject the session into the controller. What I wanted to know was, will it be a bad idea/pattern to just make an extension method like :
public static ISession GetNHibernateSession(this Controller controller)
{
return SessionFactory.OpenSession();
}
so that the session can be instantiated when required like :
public ActionResult DoSomething()
{
using( var session = this.GetNHibernateSession())
{
// Do something with the session
}
}
reasons why this may be a good/bad idea will be greatly appreciated
Good:
It's simple
It just works
Bad:
You are doing session management, even if it's just a three lines, all over your code
With an extension method, you can't replace the behavior for testing
In short, for small, RAD and proof-of-concept projects, your idea will work just fine. For more complex development, it's probably better to extract session management from the controllers, at least moving it to a base class.
I need to apply filtering by requesting host name on all database calls in my Web API service.
This filtering works like so:
lookup the Site to profile against based on the requesting hostname
Apply Site.Id on all subsequent data access calls made in the request
Essentially a global filter so so that data returned by the API service is always contained to the host.
One solution would be to pass the host name in as an argument on all my service methods like so:
public IEnumerable<Profiles> GetProfiles ()
{
var host = HttpContext.Current.Request.ServerVariables["SERVER_NAME"];
return profilesService.Get(host);
}
But since this is a consistent rule on all requests I would like to come up with a more elegant way to handle this so my service calls are just profileSerivce.Get();
I think I need to inject a ISiteLocator into my service layer that has either the host name or even better the Id already retrieved from the database that I can then apply. But I'm struggling with this on how and where I can reference the HttpContext to get the host name and also if it was possible to optimise this using StructureMap lifecycles.
I think I need to inject a ISiteLocator into my service layer
It seems to me you are heading into the right direction.
I'm struggling with this on how and where I can reference the
HttpContext
This is really simple actually. Define the ISiteLocator in your business layer and define an AspNetSiteLocator implementation into your ASP.NET web application, preferably close to (or inside) your Composition Root. That implementation might look like this:
public class AspNetSiteLocator : ISiteLocator
{
private readonly ISiteRepository siteRepository;
public AspNetSiteLocator(ISiteRepository siteRepository)
{
this.siteRepository = siteRepository;
}
Site ISiteLocator.GetCurrentSite()
{
return this.siteRepository.GetById(CurrentHostName);
}
private static string CurrentHostName
{
get
{
return HttpContext.Current.Request
.ServerVariables["SERVER_NAME"];
}
}
}
that has either the host name or even better the Id already retrieved
from the database
Try to let your ISiteLocator return data in a way that is most convenient to the consumers of that locator. In my example I returned a Site entity (if you have such an entity in your domain). This is probably more convenient than the host name or the Id, since consumers possibly have to query for the site again thereselves. However, perhaps Id is the most convenient, but that's up to you to find out.
how [...] to optimise this using StructureMap lifecycles
The implementation above doesn't have any state, so it can be registered with any lifetime; singleton for instance. However, every call to ISiteLocator.GetCurrentSite() will result in a new request to the ISiteRepository, which can cause too much overhead. In that case you probably want an implementation that stores the Site in a private field and always returns that instance. In that case you shoud register that implementation on a 'Per Web Request' basis (since the SERVER_NAME will not change during the request).