2014-08-27 3 views
0

У меня есть фильтр авторизации веб-api, который применяется к базовому контроллеру веб-контроллера api. Тип авторизации - Basic. Фильтр авторизации использует IAutofacAuthenticationFilter и использует некоторые службы, внедренные в autofac, для выполнения авторизации и аутентификации.Фильтр авторизации WebApi

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

public void OnChallenge(HttpAuthenticationChallengeContext context) { 
    var host = context.Request.RequestUri.DnsSafeHost; 
    context.Request.CreateResponse(HttpStatusCode.Unauthorized, "Unauthenticated request"); 
    context.Request.Headers.Add("WWW-Authenticate", string.Format("Basic realm=\"{0}\"", host)); 
} 

Однако, когда запрос POST сделан, все называется так же, как и описанный выше метод вызывается, как и ожидалось, но запрос продолжает обработку, перейдя к фактическому действию контроллера.

OnAuthorization не модифицируется и не перегружается. Вместо

'' OnAuthenticate выглядит следующим образом:

public void OnAuthenticate(HttpAuthenticationContext context) 
    { 


     var identity = ParseAuthorizationHeader(context.ActionContext); // identity is a custom object representing the information in the auth header 
     if (identity == null) { 
      HandleUnauthorizedRequest(context.ActionContext); 
      return; 
     } 


     if (!OnAuthorizeUser(identity.Name, identity.Key, context.ActionContext)) { 
      HandleUnauthorizedRequest(context.ActionContext); 
      return; 
     } 
    } 

Вот пользовательский метод для установки основных и аутентификации пользователя:

protected virtual bool OnAuthorizeUser(KeyContainer name, string key, HttpActionContext actionContext) { 

     // get principal code ... 

     Thread.CurrentPrincipal = principal; 
     actionContext.RequestContext.Principal = principal; 
     if (HttpContext.Current != null) 
      HttpContext.Current.User = principal; 

     return true; 
    } 

Фильтр авторизации регистрируются с контейнером со следующим :

builder.Register(c => 
      new AuthorizeActionFilterAttribute(
       c.Resolve<IService>()) 
      .AsWebApiAuthenticationFilterFor<BaseApiController>() 
      .InstancePerRequest(); 

Что происходит в запросе POST, который отличается от GET и как это можно зафиксировать?

+0

Что вы делаете в методе OnAuthenticate? –

+0

@PeterLillevold Я обновил вопрос с дополнительной информацией. Интересно, что если я не использую интерфейс IAutofacAuthenticationFilter от Autofac и не разрешаю службы, которые мне нужны, используйте 'var dependecyScope = actionContext.Request.GetDependencyScope(); var lifetimeScope = dependecyScope.GetRequestLifetimeScope(); _ service = lifetimeScope.Resolve () 'и украсить контроллер Base api фильтром, проблема исчезнет. – boosts

ответ

2

Я предполагаю, что проблема связана с регистрацией фильтра InstancePerRequest. У нас есть fairly extensive FAQ on per-request scope usage и часть этого примечания: you can't have per-request dependencies in filters, потому что WebAPI кэширует экземпляры фильтров для контроллеров после их создания - единственный способ успешно выполнить эту работу (как вы обнаружили) - это использовать местоположение службы из самого фильтра. К сожалению, мы ничего не можем сделать с стороны Autofac; все это встроено и не переопределяется в WebAPI, чтобы вести себя таким образом.

Надеемся, они изменят это в ASP.NET vNext.

+0

Не кэширование не влияет на запросы GET и POST? Однако проблема возникает только при отправке сообщений. Я проверю FAQ. – boosts