Вставить учетные данные пользователя из HttpRequestContext в слой службы - PullRequest
0 голосов
/ 06 сентября 2018

У меня есть приложение .NET 4.6 WebApi 2.0 OWIN, которое обслуживает HTTP-запросы. Эти запросы проходят проверку подлинности, и мы храним определенные утверждения в RequestContext ClaimsIdentity (UserId, код клиента)

У нас также есть структура контроллеров, служб и репозитория.

Наши Сервисы вводятся в Контроллеры через Ninject, а Репозитории в Сервисы.

Когда пользователь выполняет определенные запросы, нам нужно проверить их разрешения. Служба обычно должна знать: UserId, ClientCode, группы, к которым у пользователя есть доступ и разрешения для каждой группы (чтение, запись и т. Д.). Последний хранится только в базе данных.

Текущий поток при выполнении запроса: получить userId и clientCode из утверждений RequestContext, использовать этот ID пользователя для получения разрешений группы из базы данных. Создайте объект UserCredentials с этими свойствами.

Этот объект затем передается экземплярам Сервиса после того, как они были введены Это пример:

public PeopleController(IPeopleService peopleService, IUserManagementService userManagementService)
    {
        var clientCode = RequestContext.GetClientCode();
        var userId = RequestContext.GetUserId();
        var permissions = userManagementService.GetUserPermissions(userId, clientCode);
        }

        peopleService.InjectCredentials(new services.Models.UserCredentials()
        {
            ClientCode = clientCode,
            UserId = UserId,
            Permissions = UserPermissions

        });
        _peopleService = peopleService;
    }

Это не выглядит очень элегантно для нас, так как нам нужно повторять этот код везде и сделать IPeopleService зависимым, что пользователь не забудет вызвать метод InjectCredentials.

Итак, мой вопрос: как я могу сделать этот класс UserCredentials Injectable таким образом, чтобы его можно было передать в качестве параметра конструктору IPeopleService?

Основной блок состоит в том, что он зависит от HttpRequestContext, который доступен только на самом контроллере

Спасибо

РЕДАКТИРОВАТЬ: Я знаю, что объект UserCredentials также может быть передан в качестве параметра для каждого метода службы (который на самом деле лучше, чем метод InjectCredentials)

Ответы [ 2 ]

0 голосов
/ 06 сентября 2018

Я нашел один способ, который возможен, но я не думаю, что он рекомендован из-за использования HttpContext.Current.user

kernel.Bind<UserCredentials>().ToMethod(CreateUserCredentials);


private static UserCredentials CreateUserCredentials(IContext arg)
    {
        var identity = HttpContext.Current.User as ClaimsPrincipal;

        int userId = identity.Identity.GetUserId();
        string clientCode = identity.Identity.GetClientCode();
        var userManagementService = kernel.Get<IUserManagementService>();
        if (userId != 0)
        {
            var permisssions = userManagementService.GetUserPermissions(userId, userType, clientCode);
        }
        return new UserCredentials()
        {
            ClientCode = clientCode,
            UserId = userId,
            Permissions = userManagementService.GetUserPermissions(userId, clientCode)
        };

    }

Теперь объект UserCredentials можно добавить в конструкторы в качестве параметра и правильно инициализировать.

0 голосов
/ 06 сентября 2018

вместо введения модели, В вашей реализации IUserManagementService введите IHttpContextAccessor. Затем реализуйте метод, чтобы делать то, что вы делаете в контроллере. Пусть этот метод будет отвечать за выборку пользовательских данных для вас.

public class UserManagementService : IUserManagementService 
{
   private readonly IHttpContext httpContext;

   public UserManagementService (IHttpContext httpContext)
   {
      this.httpContext = httpContext;
   }



   public UserCredentials GetUserDetails()
   {

new services.Models.UserCredentials()
    {
        ClientCode = clientCode,
        UserId = UserId,
        Permissions = UserPermissions

    });
   }

}

Наконец, добавьте этот сервис в любой другой сервис, где вам нужны эти данные.

PeopleController(IPeopleService peopleService, IUserManagementService userManagementService)
...