Asp.net core 创建从AuthorizationFilter继承的自定义AuthorizationFilter时未调用OnAuthorizationAsync
我创建了一个自定义授权筛选器,如下所示:Asp.net core 创建从AuthorizationFilter继承的自定义AuthorizationFilter时未调用OnAuthorizationAsync,asp.net-core,asp.net-core-webapi,asp.net-core-3.1,Asp.net Core,Asp.net Core Webapi,Asp.net Core 3.1,我创建了一个自定义授权筛选器,如下所示: public class BearerTokenAuthorizeFilter : AuthorizeFilter { public override async Task OnAuthorizationAsync(AuthorizationFilterContext context) { await base.OnAuthorizationAsync(context); if (conte
public class BearerTokenAuthorizeFilter : AuthorizeFilter
{
public override async Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
await base.OnAuthorizationAsync(context);
if (context.Result is ChallengeResult)
{
// Then return a problem detail
ObjectResult result = new ObjectResult(new ProblemDetails
{
Type = ProblemDetailsTypes.Unauthorized,
Title = ReasonPhrases.GetReasonPhrase(StatusCodes.Status401Unauthorized),
Status = StatusCodes.Status401Unauthorized,
Detail = ProblemDetailsDescriptions.Unauthorized
});
result.ContentTypes.Add(new MediaTypeHeaderValue(new Microsoft.Extensions.Primitives.StringSegment("application/problem+json")));
context.Result = result;
await context.HttpContext.ChallengeAsync();
}
else if (context.Result is ForbidResult)
{
context.Result = new StatusCodeResult(StatusCodes.Status403Forbidden);
await context.HttpContext.ForbidAsync();
}
}
}
services.AddMvcCore(options =>
{
options.Filters.Add<BearerTokenAuthorizeFilter>();
});
public class BearerTokenAuthorizeConvention : IControllerModelConvention
{
private AuthorizationPolicy _policy;
public BearerTokenAuthorizeConvention(AuthorizationPolicy policy)
{
_policy = policy;
}
public void Apply(ControllerModel controller)
{
if (controller.Filters.OfType<BearerTokenAuthorizeFilter>().FirstOrDefault() == null)
{
//default policy only used when there is no authorize filter in the controller
controller.Filters.Add(new BearerTokenAuthorizeFilter(_policy));
}
}
}
// Configure application filters and conventions
services.Configure<MvcOptions>(options =>
{
AuthorizationPolicy defaultPolicy = new AuthorizationOptions().DefaultPolicy;
options.Conventions.Add(new BearerTokenAuthorizeConvention(defaultPolicy));
});
我正在按如下方式注册此筛选器:
public class BearerTokenAuthorizeFilter : AuthorizeFilter
{
public override async Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
await base.OnAuthorizationAsync(context);
if (context.Result is ChallengeResult)
{
// Then return a problem detail
ObjectResult result = new ObjectResult(new ProblemDetails
{
Type = ProblemDetailsTypes.Unauthorized,
Title = ReasonPhrases.GetReasonPhrase(StatusCodes.Status401Unauthorized),
Status = StatusCodes.Status401Unauthorized,
Detail = ProblemDetailsDescriptions.Unauthorized
});
result.ContentTypes.Add(new MediaTypeHeaderValue(new Microsoft.Extensions.Primitives.StringSegment("application/problem+json")));
context.Result = result;
await context.HttpContext.ChallengeAsync();
}
else if (context.Result is ForbidResult)
{
context.Result = new StatusCodeResult(StatusCodes.Status403Forbidden);
await context.HttpContext.ForbidAsync();
}
}
}
services.AddMvcCore(options =>
{
options.Filters.Add<BearerTokenAuthorizeFilter>();
});
public class BearerTokenAuthorizeConvention : IControllerModelConvention
{
private AuthorizationPolicy _policy;
public BearerTokenAuthorizeConvention(AuthorizationPolicy policy)
{
_policy = policy;
}
public void Apply(ControllerModel controller)
{
if (controller.Filters.OfType<BearerTokenAuthorizeFilter>().FirstOrDefault() == null)
{
//default policy only used when there is no authorize filter in the controller
controller.Filters.Add(new BearerTokenAuthorizeFilter(_policy));
}
}
}
// Configure application filters and conventions
services.Configure<MvcOptions>(options =>
{
AuthorizationPolicy defaultPolicy = new AuthorizationOptions().DefaultPolicy;
options.Conventions.Add(new BearerTokenAuthorizeConvention(defaultPolicy));
});
我在控制器上添加了
Authorize
属性。每当我向端点发送未经授权的请求时,我的自定义筛选器从未被调用,我也不知道为什么?我的目标是,如果请求未经授权向消费者提供比状态代码多一点的信息,则返回问题详细信息。为什么没有调用我的筛选器?尝试实施iaauthorizationfilter
或IAsyncAuthorizationFilter
而不是authorizationfilter
。这对我有用。我还注意到,GetFilter(…)
方法直接在AuthorizationApplicationModelProvider
中返回AuthorizeFilter
实例,当filter类实现AuthorizeFilter
时。但是当filter实现iaauthorizationfilter
或IAsyncAuthorizationFilter
时,我认为这是ASP.NET中的问题,请尝试实现iaauthorizationfilter
或IAsyncAuthorizationFilter
而不是authorizationfilter
。这对我有用。我还注意到,GetFilter(…)
方法直接在AuthorizationApplicationModelProvider
中返回AuthorizeFilter
实例,当filter类实现AuthorizeFilter
时。但是当filter实现IAuthorizationFilter
或IAsyncAuthorizationFilter
这个方法没有被调用时,我认为这是ASP.NET中的问题我最终实现了我自己的IControllerModelConvention
类,它看起来像这样:
public class BearerTokenAuthorizeFilter : AuthorizeFilter
{
public override async Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
await base.OnAuthorizationAsync(context);
if (context.Result is ChallengeResult)
{
// Then return a problem detail
ObjectResult result = new ObjectResult(new ProblemDetails
{
Type = ProblemDetailsTypes.Unauthorized,
Title = ReasonPhrases.GetReasonPhrase(StatusCodes.Status401Unauthorized),
Status = StatusCodes.Status401Unauthorized,
Detail = ProblemDetailsDescriptions.Unauthorized
});
result.ContentTypes.Add(new MediaTypeHeaderValue(new Microsoft.Extensions.Primitives.StringSegment("application/problem+json")));
context.Result = result;
await context.HttpContext.ChallengeAsync();
}
else if (context.Result is ForbidResult)
{
context.Result = new StatusCodeResult(StatusCodes.Status403Forbidden);
await context.HttpContext.ForbidAsync();
}
}
}
services.AddMvcCore(options =>
{
options.Filters.Add<BearerTokenAuthorizeFilter>();
});
public class BearerTokenAuthorizeConvention : IControllerModelConvention
{
private AuthorizationPolicy _policy;
public BearerTokenAuthorizeConvention(AuthorizationPolicy policy)
{
_policy = policy;
}
public void Apply(ControllerModel controller)
{
if (controller.Filters.OfType<BearerTokenAuthorizeFilter>().FirstOrDefault() == null)
{
//default policy only used when there is no authorize filter in the controller
controller.Filters.Add(new BearerTokenAuthorizeFilter(_policy));
}
}
}
// Configure application filters and conventions
services.Configure<MvcOptions>(options =>
{
AuthorizationPolicy defaultPolicy = new AuthorizationOptions().DefaultPolicy;
options.Conventions.Add(new BearerTokenAuthorizeConvention(defaultPolicy));
});
公共类BearTokenAuthorizeConvention:IControllerModelConvention
{
私人授权政策(u政策),;
公共承运人授权公约(授权政策)
{
_政策=政策;
}
公共无效应用(控制器模型控制器)
{
if(controller.Filters.OfType().FirstOrDefault()==null)
{
//默认策略仅在控制器中没有授权筛选器时使用
controller.Filters.Add(新的BealerTokenAuthorizeFilter(_策略));
}
}
}
这将在每个控制器上执行一次。然后我注册了这样一个公约:
public class BearerTokenAuthorizeFilter : AuthorizeFilter
{
public override async Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
await base.OnAuthorizationAsync(context);
if (context.Result is ChallengeResult)
{
// Then return a problem detail
ObjectResult result = new ObjectResult(new ProblemDetails
{
Type = ProblemDetailsTypes.Unauthorized,
Title = ReasonPhrases.GetReasonPhrase(StatusCodes.Status401Unauthorized),
Status = StatusCodes.Status401Unauthorized,
Detail = ProblemDetailsDescriptions.Unauthorized
});
result.ContentTypes.Add(new MediaTypeHeaderValue(new Microsoft.Extensions.Primitives.StringSegment("application/problem+json")));
context.Result = result;
await context.HttpContext.ChallengeAsync();
}
else if (context.Result is ForbidResult)
{
context.Result = new StatusCodeResult(StatusCodes.Status403Forbidden);
await context.HttpContext.ForbidAsync();
}
}
}
services.AddMvcCore(options =>
{
options.Filters.Add<BearerTokenAuthorizeFilter>();
});
public class BearerTokenAuthorizeConvention : IControllerModelConvention
{
private AuthorizationPolicy _policy;
public BearerTokenAuthorizeConvention(AuthorizationPolicy policy)
{
_policy = policy;
}
public void Apply(ControllerModel controller)
{
if (controller.Filters.OfType<BearerTokenAuthorizeFilter>().FirstOrDefault() == null)
{
//default policy only used when there is no authorize filter in the controller
controller.Filters.Add(new BearerTokenAuthorizeFilter(_policy));
}
}
}
// Configure application filters and conventions
services.Configure<MvcOptions>(options =>
{
AuthorizationPolicy defaultPolicy = new AuthorizationOptions().DefaultPolicy;
options.Conventions.Add(new BearerTokenAuthorizeConvention(defaultPolicy));
});
//配置应用程序筛选器和约定
配置(选项=>
{
AuthorizationPolicy defaultPolicy=新建AuthorizationOptions().defaultPolicy;
添加(新BealerTokenAuthorizeConvention(defaultPolicy));
});
此时,我拥有的每个控制器都将被这个自定义过滤器标记,它将调用
AuthorizeFilter
的基本实现。我之所以想从AuthorizeFilter
派生,是因为我想调用authorized
的默认实现,然后自己处理失败的响应。我认为我可以完成这项功能,但不知何故仍然只能使用Authorize
属性。这似乎是不可能的。除非是我遗漏了什么?我最终实现了自己的IControllerModelConvention
类,该类如下所示:
public class BearerTokenAuthorizeFilter : AuthorizeFilter
{
public override async Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
await base.OnAuthorizationAsync(context);
if (context.Result is ChallengeResult)
{
// Then return a problem detail
ObjectResult result = new ObjectResult(new ProblemDetails
{
Type = ProblemDetailsTypes.Unauthorized,
Title = ReasonPhrases.GetReasonPhrase(StatusCodes.Status401Unauthorized),
Status = StatusCodes.Status401Unauthorized,
Detail = ProblemDetailsDescriptions.Unauthorized
});
result.ContentTypes.Add(new MediaTypeHeaderValue(new Microsoft.Extensions.Primitives.StringSegment("application/problem+json")));
context.Result = result;
await context.HttpContext.ChallengeAsync();
}
else if (context.Result is ForbidResult)
{
context.Result = new StatusCodeResult(StatusCodes.Status403Forbidden);
await context.HttpContext.ForbidAsync();
}
}
}
services.AddMvcCore(options =>
{
options.Filters.Add<BearerTokenAuthorizeFilter>();
});
public class BearerTokenAuthorizeConvention : IControllerModelConvention
{
private AuthorizationPolicy _policy;
public BearerTokenAuthorizeConvention(AuthorizationPolicy policy)
{
_policy = policy;
}
public void Apply(ControllerModel controller)
{
if (controller.Filters.OfType<BearerTokenAuthorizeFilter>().FirstOrDefault() == null)
{
//default policy only used when there is no authorize filter in the controller
controller.Filters.Add(new BearerTokenAuthorizeFilter(_policy));
}
}
}
// Configure application filters and conventions
services.Configure<MvcOptions>(options =>
{
AuthorizationPolicy defaultPolicy = new AuthorizationOptions().DefaultPolicy;
options.Conventions.Add(new BearerTokenAuthorizeConvention(defaultPolicy));
});
公共类BearTokenAuthorizeConvention:IControllerModelConvention
{
私人授权政策(u政策),;
公共承运人授权公约(授权政策)
{
_政策=政策;
}
公共无效应用(控制器模型控制器)
{
if(controller.Filters.OfType().FirstOrDefault()==null)
{
//默认策略仅在控制器中没有授权筛选器时使用
controller.Filters.Add(新的BealerTokenAuthorizeFilter(_策略));
}
}
}
这将在每个控制器上执行一次。然后我注册了这样一个公约:
public class BearerTokenAuthorizeFilter : AuthorizeFilter
{
public override async Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
await base.OnAuthorizationAsync(context);
if (context.Result is ChallengeResult)
{
// Then return a problem detail
ObjectResult result = new ObjectResult(new ProblemDetails
{
Type = ProblemDetailsTypes.Unauthorized,
Title = ReasonPhrases.GetReasonPhrase(StatusCodes.Status401Unauthorized),
Status = StatusCodes.Status401Unauthorized,
Detail = ProblemDetailsDescriptions.Unauthorized
});
result.ContentTypes.Add(new MediaTypeHeaderValue(new Microsoft.Extensions.Primitives.StringSegment("application/problem+json")));
context.Result = result;
await context.HttpContext.ChallengeAsync();
}
else if (context.Result is ForbidResult)
{
context.Result = new StatusCodeResult(StatusCodes.Status403Forbidden);
await context.HttpContext.ForbidAsync();
}
}
}
services.AddMvcCore(options =>
{
options.Filters.Add<BearerTokenAuthorizeFilter>();
});
public class BearerTokenAuthorizeConvention : IControllerModelConvention
{
private AuthorizationPolicy _policy;
public BearerTokenAuthorizeConvention(AuthorizationPolicy policy)
{
_policy = policy;
}
public void Apply(ControllerModel controller)
{
if (controller.Filters.OfType<BearerTokenAuthorizeFilter>().FirstOrDefault() == null)
{
//default policy only used when there is no authorize filter in the controller
controller.Filters.Add(new BearerTokenAuthorizeFilter(_policy));
}
}
}
// Configure application filters and conventions
services.Configure<MvcOptions>(options =>
{
AuthorizationPolicy defaultPolicy = new AuthorizationOptions().DefaultPolicy;
options.Conventions.Add(new BearerTokenAuthorizeConvention(defaultPolicy));
});
//配置应用程序筛选器和约定
配置(选项=>
{
AuthorizationPolicy defaultPolicy=新建AuthorizationOptions().defaultPolicy;
添加(新BealerTokenAuthorizeConvention(defaultPolicy));
});
此时,我拥有的每个控制器都将被这个自定义过滤器标记,它将调用
AuthorizeFilter
的基本实现。我之所以想从AuthorizeFilter
派生,是因为我想调用authorized
的默认实现,然后自己处理失败的响应。我认为我可以完成这项功能,但不知何故仍然只能使用Authorize
属性。这似乎是不可能的。除非它是一个I'm missing something?请检查Startup.cs文件中的Configure方法,确保已添加UseAuthentication和UseAuthentication中间件,代码如下:app.UseAuthentication();app.UseAuthorization()
。请检查Startup.cs文件中的Configure方法,确保已添加UseAuthentication和UseAuthentication中间件,代码如下:app.UseAuthentication();app.UseAuthorization()代码>。我想问题是,我用Authorize
属性标记了控制器,而不是用BearerTokenAuthorize
标记了控制器。所以我的自定义过滤器从未被调用。我想问题是,我用Authorize
属性标记了控制器,而不是用BearerTokenAuthorize
标记了控制器。所以我的自定义过滤器从未被调用。