C# 在Web API[Net.Core]上授权失败时登录到数据库

C# 在Web API[Net.Core]上授权失败时登录到数据库,c#,filter,asp.net-core,authorization,asp.net-core-webapi,C#,Filter,Asp.net Core,Authorization,Asp.net Core Webapi,我有一个.Net核心Web API,带有自定义的基于策略的授权(在JWT上检查声明和声明值的策略) 每次用户调用Web API函数时,我都需要记录(到数据库),即使授权失败(尤其是在失败时) 为此,我重写了这些方法OnActionExecuting和OnResultExecuted(因为我想在一个筛选器上记录每个请求,在另一个筛选器中记录请求的结果)。但是,如果授权失败,两个过滤器都不会触发 这是因为授权过滤器先于其他过滤器(如果请求未经授权,则短路管道) 因此,当用户未经授权调用某个方法时,我

我有一个.Net核心Web API,带有自定义的基于策略的授权(在JWT上检查声明和声明值的策略)

每次用户调用Web API函数时,我都需要记录(到数据库),即使授权失败(尤其是在失败时)

为此,我重写了这些方法
OnActionExecuting
OnResultExecuted
(因为我想在一个筛选器上记录每个请求,在另一个筛选器中记录请求的结果)。但是,如果授权失败,两个过滤器都不会触发

这是因为授权过滤器先于其他过滤器(如果请求未经授权,则短路管道)

因此,当用户未经授权调用某个方法时,我无法记录它(我使用Serilog在服务器上编写日志文件,在授权失败时可以正常工作,但我希望将其记录到数据库中,就像在授权正常时一样)

我尝试在授权之前或之后编写一些过滤器,但我无法做到。可能是我的思维方式不对,更简单

我读了所有这些,但我还没弄明白:

谢谢

您是否尝试过以下选项:

使用覆盖顺序的全局过滤器,例如:

public void ConfigureServices(IServiceCollection services)
{

    services
        .AddMvc(options =>
            {
                options.Filters.Add(typeof(MyLoggingFilter), -2);
                options.Filters.Add(typeof(MyAuthFilter), -1);
            });
}
对于基于属性的过滤器,您可以实现IOrderedFilter

[AttributeUsage(AttributeTargets.Class|AttributeTargets.Method)]
internal sealed class MyAuthorizationAttribute : Attribute, IAuthorizationFilter, IOrderedFilter
{
    public int Order => -2;
}
将记录器注入AuthFilter本身

public MyAuthFilter(ILoggerFactory loggerFactory)
{
    _logger = loggerFactory.CreateLogger<MyAuthFilter>();
}
公共MyAuthFilter(ILoggerFactory loggerFactory)
{
_logger=loggerFactory.CreateLogger();
}
您是否尝试过以下选项:

使用覆盖顺序的全局过滤器,例如:

public void ConfigureServices(IServiceCollection services)
{

    services
        .AddMvc(options =>
            {
                options.Filters.Add(typeof(MyLoggingFilter), -2);
                options.Filters.Add(typeof(MyAuthFilter), -1);
            });
}
对于基于属性的过滤器,您可以实现IOrderedFilter

[AttributeUsage(AttributeTargets.Class|AttributeTargets.Method)]
internal sealed class MyAuthorizationAttribute : Attribute, IAuthorizationFilter, IOrderedFilter
{
    public int Order => -2;
}
将记录器注入AuthFilter本身

public MyAuthFilter(ILoggerFactory loggerFactory)
{
    _logger = loggerFactory.CreateLogger<MyAuthFilter>();
}
公共MyAuthFilter(ILoggerFactory loggerFactory)
{
_logger=loggerFactory.CreateLogger();
}

听起来您想在.NET管道中记录更高的日志? 您可以查看DelegatingHandler类,而不是过滤器。这些处理程序在管道中执行得更高,在身份验证过滤器之前

public class MyLogMessageHandler : DelegatingHandler
{
    protected override async System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {

      // Do logging with request or HttpContext.Current

    }
}
公共类MyLogMessageHandler:DelegatingHandler
{
受保护的重写异步System.Threading.Tasks.Task SendAsync(
HttpRequestMessage请求,CancellationToken CancellationToken)
{
//使用request或HttpContext.Current执行日志记录
}
}
在global.asax.cs(或等效文件)中,u将注册处理程序:

GlobalConfiguration.Configuration.MessageHandler.Add(新的MyLogMessageHandler())

看看


此外,我们还有一个API日志记录和分析解决方案,这可能会对您有所帮助,尤其是当您使用Azure时,因为有一个Azure扩展。(完全披露我是首席执行官)

听起来你想在.NET管道中登录更高的位置? 您可以查看DelegatingHandler类,而不是过滤器。这些处理程序在管道中执行得更高,在身份验证过滤器之前

public class MyLogMessageHandler : DelegatingHandler
{
    protected override async System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {

      // Do logging with request or HttpContext.Current

    }
}
公共类MyLogMessageHandler:DelegatingHandler
{
受保护的重写异步System.Threading.Tasks.Task SendAsync(
HttpRequestMessage请求,CancellationToken CancellationToken)
{
//使用request或HttpContext.Current执行日志记录
}
}
在global.asax.cs(或等效文件)中,u将注册处理程序:

GlobalConfiguration.Configuration.MessageHandler.Add(新的MyLogMessageHandler())

看看


此外,我们还有一个API日志记录和分析解决方案,这可能会对您有所帮助,尤其是当您使用Azure时,因为有一个Azure扩展。(完全披露我是首席执行官)

谢谢@Derric,我会试试(我不使用Azure)再次感谢你,这就是我想要的。我尝试使用DelegatingHanlder(您提供的链接非常有用!),然后我意识到在.NETCore中而不是HTTP hanlder中使用了。所以我创建了一个中间件,比如,我需要进行更多的测试,但它正在工作:)谢谢@Derric,我会尝试(我不使用Azure)再次感谢你,这就是我想要的。我尝试使用DelegatingHanlder(您提供的链接非常有用!),然后我意识到在.NETCore中而不是HTTP hanlder中使用了。所以我创建了一个中间件,比如,我需要进行更多的测试,但它正在工作:)我不知道过滤器的顺序可以更改,谢谢@Fionn,我会尝试一下(并注入记录器)。问题是,我没有自己的“AuthFilter”,我将授权添加为服务,而不是MVC选项(services.AddAuthorization(options=>{options.AddPoliciy(使用JWT声明的东西)}),有点像我对MVC声明授权不太熟悉,但是你可以尝试在内置处理程序运行之前插入一个过滤器或中间件,谢谢@Fionn,也就是说,我创建了一个中间件并在反自动验证之前插入了它。我不知道过滤器顺序可以更改,谢谢@Fionn,我会尝试的(并插入记录器)问题是,我没有自己的“AuthFilter”,我将授权添加为服务,而不是MVC选项(services.AddAuthorization(options=>{options.AddPoliciy(使用JWT声明的东西)})),有点像我不太熟悉MVC声明授权,但您可以尝试在内置处理程序运行之前插入过滤器或中间件,谢谢@Fionn,也就是说,我创建了一个中间件,并在反自动验证之前插入了它