我有一个web api授权过滤器,应用于web api控制器的基本控制器。授权类型为Basic。授权过滤器使用IAutofacAuthenticationFilter,并使用一些autofac注入服务来执行授权和身份验证。
在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 :(得分: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中更改它。