Ninject Asp. Net Порядок выполнения фильтра авторизации WebApi - PullRequest
1 голос
/ 27 января 2020

У меня есть фильтр авторизации, который проверяет токен. Фильтр реализован как IAuthorizationFilter с классом атрибута reparate, чтобы включить внедрение конструктора. Это отлично работает. Когда токен проверяется, он сохраняется в Thread.CurrentPrincipal.

Проблема заключается в том, что я использую его в контроллере с таким атрибутом. В контроллер также введен класс, в котором текущий пользователь должен быть известен. Необходимо использовать правильную строку подключения для базы данных, принадлежащей группе пользователей.

[TestAuthorizeToken]
public class TestController : BaseApiController
{
    IUserDetails user;

    public TestController(IUserDetails _user)
    {
        this.user = _user;
    }

    [HttpGet]
    [Route("GetClientCode")]
    public string GetClientCode()
    {
        return user.ClientCode;
    }
}

Я предполагал, что код фильтра всегда будет запускаться первым, поэтому идентификация затем проверяется и сохраняется в потоке.

Но, к моему удивлению, класс UserDetails создается до запуска кода фильтра. Поэтому я не могу использовать идентификатор в экземпляре UserDetails.

Есть ли способ убедиться, что код авторизации - это первое, что запускается в этом случае? Или я что-то упускаю?

Соответствующие привязки:

kernel.BindHttpFilter<TestAuthorizeTokenFilter>(System.Web.Http.Filters.FilterScope.Controller)
    .WhenControllerHas<TestAuthorizeTokenAttribute>();

kernel.Bind<IUserDetails>().To<UserDetails>();

kernel.Bind<IMasterUserRepoFactory>().ToFactory();

Фильтр:

public class TestAuthorizeTokenAttribute : System.Web.Http.Filters.AuthorizationFilterAttribute
{
}

public class TestAuthorizeTokenFilter : System.Web.Http.Filters.IAuthorizationFilter
{
    private IMasterUserRepo masterUserRepo;
    private IMasterUserRepoFactory masterUserRepoFactory;

    public TestAuthorizeTokenFilter(IMasterUserRepoFactory masterUserRepoFactory)
    {
        this.masterUserRepoFactory = masterUserRepoFactory;
    }

    public bool AllowMultiple
    {
        get
        {
            return false;
        }
    }

    public Task<HttpResponseMessage> ExecuteAuthorizationFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
    {
        if (Thread.CurrentPrincipal.Identity.IsAuthenticated)
        {
            return continuation();  
        }

        masterUserRepo = this.masterUserRepoFactory.Create();

        AuthenticationHeaderValue authHeader = actionContext.Request.Headers.Authorization;

        if (authHeader != null)
        {
            // Simplified
            string token = authHeader.Parameter;
            var masterUser = masterUserRepo.GetItemByToken(token);
            // ...
            var identity = new GenericIdentity(token);
            var principal = new GenericPrincipal(identity, null);
            Thread.CurrentPrincipal = principal;

            return continuation();  
        }

        return Task.FromResult(new HttpResponseMessage(HttpStatusCode.Unauthorized));
    }
}

public interface IMasterUserRepoFactory
{
    IMasterUserRepo Create();
}
...