Как я могу передать аутентифицированный идентификатор пользователя проекту библиотеки классов в ядре asp. net через DI? - PullRequest
1 голос
/ 04 апреля 2020

У меня есть приложение NLayers:

  • asp. net core mvc
  • asp. net web api

и некоторые из моих библиотек классов :

  • DataLayer
  • DomainClasses
  • Модели
  • Сервисы

вот мой BaseService в ServicesLayer:

public abstract partial class BaseService 
{
   protected BaseService(AppDbContext dbContext
                        , UserManager<MyApplicationUser> userManager
                        , int authenticatedUserId)
   {
       DbContext = dbContext;
       AuthenticatedUserId = authenticatedUserId;
       MyUserManager = userManager;

       Init();
  }

  public AppDbContext DbContext { get; }
  protected UserManager<MyApplicationUser> MyUserManager;
  public string AuthenticatedUserId { get; }

  protected virtual void Init()
  {
    // 
  }

  ...

}

и один из моих дочерних классов обслуживания:

public class BookService :BaseService
{
   public BookService(AppDbContext dbContext
       , UserManager<MyApplicationUser> userManager 
        , int authenticatedUserId)

        :base(dbContext,userManager, authenticatedUserId)
    {

    }
}

Я хочу получить доступ аутентифицированный идентификатор пользователя (из Asp net core) в моих службах (библиотека классов). Как я могу передать его через DI или что-то еще?

Обновлено на основании предложения @ Фрэнка:

public class CommonServicesContainer
{
    public AppDbContext DbContext { get; set; }
    public AppUserManager UserManager { get; set; }
    public int AuthenticatedUserId{ get; set; }

    public CommonServicesContainer(AppDbContext appDbContext, AppUserManager userManager, string authenticatedUserId)
    {
        DbContext = dbContext;
        UserManager = userManager;
        AuthenticatedUserId = autheticatedUserId;
    }
}

мой запуск:

        services.AddScoped<AppDbContext>();
        services.AddScoped<AppUserManager>();

        services.AddScoped(x =>
        {
            var authenticatedUserId = x.GetRequiredService<IHttpContextAccessor>().HttpContext.User.Identity.Name;

            return new CommonServicesContainer(x.GetRequiredService<AppDbContext>()
                                         , x.GetRequiredService<AppUserManager>()
                                         , authenticatedUserId);
        });

AccountController:

private readonly CommonServicesContainer _commonServicesContainer;

public AccountController(CommonServicesContainer commonServicesContainer)
{
    _commonServicesContainer = commonServicesContainer;

    // ...
}


[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginInputModel model)
{
   // ... 
   if(ModelState.IsValid)
   {
                var isValid = await _usersService.AreCredentialsValidAsync(model.Username, model.Password);

   if(isValid)
   {
       var foundUser = await _usersService.GetByUserNameAsync(model.Username);

                        await HttpContext.SignInAsync(
                                        foundUser.SubjectId,                         
                                        foundUser.UserName);

                        //_commonServicesContainer.AuthenticatedUserId = foundUser.Id;
                        // ...

   }
   // ...
}

1 Ответ

1 голос
/ 04 апреля 2020

Вы можете сделать это, зарегистрировав тип AuthenticatedUser в качестве AddScoped.

class AuthenticatedUser {
  public int? UserId {get;set;}
  public bool IsAuthenticated => int.HasValue;
}

в Startup.cs вашего проекта AspNetCore:

public IServiceProvider ConfigureServices(IServiceCollection services) {
   ...
   services.AddScoped<AuthenticatedUser>();
   ...
}

Где-то, где вы делаете аутентификацию, вы получить AuthenticatedUser и установить UserId.

Поскольку AuthenticatedUser добавляется как область действия, он действует как глобальный (тот же экземпляр) для конкретной области действия httprequest. Таким образом, все .GetService<AuthenticatedUser> / .GetRequiredService<AuthenticatedUser> будут иметь один и тот же экземпляр - в пределах одной и той же области.

Каждый http-запрос имеет свою собственную область и, следовательно, также свой собственный AuthenticatedUser.

Когда пользователь Аутентифицирован, используя AspNetCore Identity, вы можете найти AspNetUsers Id по:

if( httpContext.User.Identity.IsAuthenticated ) {
  var userIdClaim = httpContext.User.Claims.SingleOrDefault(c => c.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier");
  var aspNetUsersId = userIdClaim?.Value ?? 0;
}

Это можно сделать как Middleware, затем установить AuthenticatedUser.UserId.

...