Web API审核日志记录

kri*_*son 9 c# asp.net asp.net-web-api

我需要审核对我的Web API的日志调用,理想情况下我想使用属性,例如:

    [HttpPost, Auditing]
    public dynamic MyAPICall()
Run Code Online (Sandbox Code Playgroud)

Attribute应该能够在执行之前和之后拦截API调用,以便记录参数以及API调用运行多长时间.

使用MVC,我可以创建一个ActionFilterAttribute衍生物并覆盖OnActionExecuted和OnActionExecuting.

在Web API世界中是否可以等效?

Jas*_*ley 16

我会使用消息处理程序而不是属性.

public class LoggingHandler : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        LogRequest(request);

        return base.SendAsync(request, cancellationToken).ContinueWith(task =>
        {
            var response = task.Result;

            LogResponse(response);

            return response;
        });
    }

    private void LogRequest(HttpRequestMessage request)
    {
        (request.Content ?? new StringContent("")).ReadAsStringAsync().ContinueWith(x =>
        {
            Logger.Info("{4:yyyy-MM-dd HH:mm:ss} {5} {0} request [{1}]{2} - {3}", request.GetCorrelationId(), request.Method, request.RequestUri, x.Result, DateTime.Now, Username(request));
        });
    }

    private void LogResponse(HttpResponseMessage response)
    {
        var request = response.RequestMessage;
        (response.Content ?? new StringContent("")).ReadAsStringAsync().ContinueWith(x =>
        {
            Logger.Info("{3:yyyy-MM-dd HH:mm:ss} {4} {0} response [{1}] - {2}", request.GetCorrelationId(), response.StatusCode, x.Result, DateTime.Now, Username(request));
        });
    }

    private string Username(HttpRequestMessage request)
    {
        var values = new List<string>().AsEnumerable();
        if (request.Headers.TryGetValues("my-custom-header-for-current-user", out values) == false) return "<anonymous>";

        return values.First(); 
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这只是捕获日志记录的信息.记录方式/内容甚至如何查看日志的详细信息是另一回事.一个独立于这个问题的人. (4认同)

k0s*_*tya 16

为此目的,Http消息处理程序应该是一个很好的可扩展点.但请注意,并发请求内容读取可能存在一些问题.例如,Model Binder可能会在读取请求内容时尝试读取请求内容,LoggingHandler并且无法反序列化模型.要防止此类问题,只需将Wait调用添加到LogRequestLoggingInfo方法即可.

public class LoggingHandler : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        // Log the request information
        LogRequestLoggingInfo(request);

        // Execute the request
        return base.SendAsync(request, cancellationToken).ContinueWith(task =>
        {
            var response = task.Result;
            // Extract the response logging info then persist the information
            LogResponseLoggingInfo(response);
            return response;
        });
    }

    private void LogRequestLoggingInfo(HttpRequestMessage request)
    {
        if (request.Content != null)
        {
            request.Content.ReadAsByteArrayAsync()
                .ContinueWith(task =>
                    {
                        var result = Encoding.UTF8.GetString(task.Result);
                        // Log it somewhere
                    }).Wait(); // !!! Here is the fix !!!
        }
    }

    private void LogResponseLoggingInfo(HttpResponseMessage response)
    {
        if (response.Content != null)
        {
            response.Content.ReadAsByteArrayAsync()
                .ContinueWith(task =>
                {
                    var responseMsg = Encoding.UTF8.GetString(task.Result);
                    // Log it somewhere
                });
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

你可以在这里阅读更多相关信息.


小智 5

我想你有兴趣看看Web API跟踪http://www.asp.net/web-api/overview/testing-and-debugging/tracing-in-aspnet-web-api.它允许您查看Web API的内部机制.

在您的情况下,我假设您对操作的输入和输出特别感兴趣.因此,您可以像下面的示例一样修改TraceWriter以过滤掉冗余信息:

public class ActionAuditor : ITraceWriter
{
    private const string TargetOperation = "ExecuteAsync";
    private const string TargetOpeartor = "ReflectedHttpActionDescriptor";

    public void Trace(HttpRequestMessage request, string category, TraceLevel level, Action<TraceRecord> traceAction)
    {
        var rec = new TraceRecord(request, category, level);
        traceAction(rec);

        if (rec.Operation == TargetOperation && rec.Operator == TargetOpeartor)
        {
            if (rec.Kind == TraceKind.Begin)
            {
                // log the input of the action
            }
            else
            {
                // log the output of the action
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


the*_*000 5

我开发了一个库,允许您使用操作过滤器记录与 ASP.NET Web API 控制器的交互。

它可以记录操作方法调用,包括调用者信息、参数、输出、持续时间、异常等。

看一下Audit.WebApi

您可以使用以下命令快速创建使用该库的示例项目:

> dotnet new -i Audit.WebApi.Template
> dotnet new webapiaudit
Run Code Online (Sandbox Code Playgroud)