I am currently building an application where each user has an unique key stored in the users' session storage. This key is used to decrypt the users data in the database. Since the repository layer of the application handles database queries (using Dapper) I would like the decryption to take place there.
Now the problem: I can retrieve the users key from the session storage, pass it to the controller, then to the service then to the repository using a parameter of name "key" in each method that is chained. Is there a way to pass a key from the controller through to the repository layer without having to include the key manually in every call?
If there is a better solution than to store it in session storage I am open to it, if it is going to make this easier.
The encryption system I am following is as follows (from another SO answer):
You can inject IHttpContextAccessor
in your repository or other related business services to retrieve user key.
Suppose you send user key in Header
of Http requests as UserKey
:
In your Startup.cs
public void ConfigureServices(IServiceCollection services)
{
...
services.AddHttpContextAccessor();
...
}
In your Repository:
public Repository(IHttpContextAccessor httpContextAccessor, ...)
{
...
var userKey = httpContextAccessor.HttpContext.Request.Headers["UserKey"].FirstOrDefault();
// Or if you send it as cookie:
// var userKey = httpContextAccessor.HttpContext.Request.Cookies["UserKey"];
...
}
Of course you could do it like in accepted answer, but still i would not recommend it
I assume you have some assembly like ProjectName.Repositories
or ProjectName.DAL
where all of your repositories are
To use IHttpContextAccessor
there you should install Microsoft.AspNetCore.Http
as a dependency
So now your repository level knows about "what framework we are using to work with requests" and it uses current HttpContext
to get some data
But to provide low coupling between components we should not depend on details like this
So we could write some user-defined container class to transfer UserKey
to our repository level
there is code for my suggestion :
public void ConfigureServices(IServiceCollection services)
{
...
services.AddScoped<UserKeyContainer>();
services.AddTransient<IUserRepository, UserRepository>();
...
}
somewhere in the Abstraction or Dto layer you'll have
public class UserKeyContainer
{
public string UserKey { get; set; }
}
controller code :
[Route("[controller]")]
public class UserController : Controller
{
private readonly UserKeyContainer _keyContainer;
private readonly IUserRepository _repository;
public UserController(UserKeyContainer keyContainer, IUserRepository repository)
{
_keyContainer = keyContainer;
_repository = repository;
}
[HttpGet("")]
public IActionResult Get()
{
_keyContainer.UserKey = "dasdasd"; //you should get UserKey from request there
_repository.SomeMethod();
return Ok();
}
}
and repository :
public class UserRepository : IUserRepository
{
private readonly UserKeyContainer _keyContainer;
public UserRepository(UserKeyContainer keyContainer)
{
_keyContainer = keyContainer;
}
public void SomeMethod()
{
var key = _keyContainer.UserKey;
}
}
Also you could use action filters to intercept requests and set HttpContext
data to UserKey
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With