Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Configure Simple Injector to inject current authenticated user

I have a class which needs to set an IPrinciple object on construction, based on the current authenticated user.

I found some other code which I tried but it didn't work:

private readonly Lazy<IPrincipal> _principal;

public MyService(Lazy<IPrincipal> principal)
{
    _principal = principal;
}

And I configured Simple Injector like so:

container.Register(() => new Lazy<IPrincipal>(() => HttpContext.Current.User));

Apparently _principal is undefined/not set to an instance of an object when I try running this.

I also tried:

container.Register(() => new Lazy<IPrincipal>(() => Thread.CurrentPrincipal));

This allowed me to check _principal.Value.Identity.IsAuthenticated but was always returning false.

like image 584
marcusstarnes Avatar asked May 25 '16 14:05

marcusstarnes


People also ask

Is simple injector safe?

Simple Injector is thread-safe and its lock-free design allows it to scale linearly with the number of available processors and threads.

What is simple injector?

Simple Injector is a free, fast, and flexible inversion of control library that is easy to use and configure. It supports . NET Core, Xamarin, Mono, and Universal apps and is easily integrated with Web API, MVC, WCF, ASP.NET Core, etc.

How does dependency injection work?

Dependency Injection (DI) is a design pattern used to implement IoC. It allows the creation of dependent objects outside of a class and provides those objects to a class through different ways. Using DI, we move the creation and binding of the dependent objects outside of the class that depends on them.


1 Answers

The root of your problems is caused by the fact that you inject runtime data into your components during object graph construction. As explained here, this is a bad idea.

Instead, as the referenced article advices, you should delay the decision of requesting this runtime data until after the graph is built; at the time that this runtime data is available.

You can do this by creating a custom IPrincipal implementation like this:

public class HttpContextPrinciple : IPrincipal
{
    public IIdentity Identity => HttpContext.Current.User.Identity;
    public bool IsInRole(string role) => HttpContext.Current.User.IsInRole(role);
}

And register it like this:

container.RegisterSingleton<IPrincipal>(new HttpContextPrinciple());

This allows you to inject IPrincipal directly into consumers like MyService. This simplifies the consumers, since they don't have to deal with leaky abstractions such as Lazy<T>.

like image 52
Steven Avatar answered Sep 23 '22 14:09

Steven