I am trying to implement an ASP.NET Core MVC web app similar to Jason Taylor's CleanArchitecture design. In the WebUi "layer" I try to implement an abstraction of an IIdentityService
in which I want to access the ClaimsPrincipal associated with the current HttpRequest
.
After some digging through the source code on github, I found that the Controller.User
property stems from ControllerBase.HttpContext? which is derived from ControllerContext which in turn is derived from ActionContext in which the HttpContext
property is defined as
/// <summary>
/// Gets or sets the <see cref="Http.HttpContext"/> for the current request.
/// </summary>
/// <remarks>
/// The property setter is provided for unit test purposes only.
/// </remarks>
public HttpContext HttpContext
{
get; set;
}
Here I am hitting a dead end. I assume the property is initialised by some middleware (ie. .AddAuthentication() / .AddAuthorization() from Microsoft.Identity), but I would like to confirm that, so I know how to get a reference to that object in my service.
Other sources of IPrincipal
s, from which ClaimsPrincipal
I have found are
System.Web.HttpContext.Current.User
ClaimsPrincipal.Current
Thread.CurrentPrincipal
IHttpContextAccessor _httpContextAccessor;
var principal = _httpContextAccessor.HttpContext?.User;
with the documentation for IHttpContextAccessor here, but I cannot figure out which is the one Controller.User
is pointing to.
CodePudding user response:
After being hinted in the right direction by @JHBonarius in the comments, I found a documented case in the official documentation
Use HttpContext from custom components
For other framework and custom components that require access to HttpContext, the recommended approach is to register a dependency using the built-in Dependency Injection (DI) container. The DI container supplies the IHttpContextAccessor to any classes that declare it as a dependency in their constructors:
var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllersWithViews(); builder.Services.AddHttpContextAccessor(); builder.Services.AddTransient<IUserRepository, UserRepository>();
In the following example:
UserRepository declares its dependency on IHttpContextAccessor. The dependency is supplied when DI resolves the dependency chain and creates an instance of UserRepository.
public class UserRepository : IUserRepository { private readonly IHttpContextAccessor _httpContextAccessor; public UserRepository(IHttpContextAccessor httpContextAccessor) => _httpContextAccessor = httpContextAccessor; public void LogCurrentUser() { var username = _httpContextAccessor.HttpContext.User.Identity.Name; // ... } }