【问题标题】:How do we log authentication token requests in ASP.NET Web API我们如何在 ASP.NET Web API 中记录身份验证令牌请求
【发布时间】:2016-06-13 14:42:37
【问题描述】:

我们有一个 ASP.NET Web Api 应用程序,它使用 OAuth Bearer Tokens 进行身份验证,我们正在尝试实现请求/响应日志记录。

基本上它是这样工作的:
1. 用户向“/authenticate”发送请求并收到一个认证令牌
2. 用户然后使用此身份验证令牌来请求公开的 API 方法

为了记录对公开 API 方法的请求,我们使用 DelegatingHandler,它工作得非常好。

但是,DelegatingHandler 实现不会捕获对“/authenticate”的请求。

记录令牌请求是否需要不同的方法?

public abstract class MessageHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var correlationId = Guid.NewGuid();

        var requestInfo = string.Format("{0} {1}", request.Method, request.RequestUri);

        var requestContent = await request.Content.ReadAsByteArrayAsync();

        var context = ((HttpContextBase)request.Properties["MS_HttpContext"]);

        await IncomingMessageAsync(correlationId, request.Method, request.RequestUri, request.Headers, requestContent, 
            context.Request.UserHostAddress, context.Request.IsAuthenticated, context.User.Identity.Name);

        var response = await base.SendAsync(request, cancellationToken);

        byte[] responseMessage;

        responseMessage = await response.Content.ReadAsByteArrayAsync();

        await OutgoingMessageAsync(correlationId, response.StatusCode, response.Headers, responseMessage);

        return response;
    }

    protected abstract Task IncomingMessageAsync(Guid correlationId, HttpMethod requestMethod, Uri requestUri, HttpRequestHeaders requestHeaders, byte[] messageContent, string ipAddress, bool isAuthenticated, string requestMadeByUserName);
    protected abstract Task OutgoingMessageAsync(Guid correlationId, HttpStatusCode statusCode, HttpResponseHeaders responseHeaders, byte[] messageContent);
}

使用 OAuth 代码编辑

[assembly: OwinStartup(typeof(MyApp.Infrastructure.IdentityConfig))]
namespace MyApp.Infrastructure
{
    public class IdentityConfig
    {
        public void Configuration(IAppBuilder app)
        {
            app.CreatePerOwinContext<ApplicationIdentityDbContext>(() => ApplicationIdentityDbContext.Create(ConfigurationDataProvider.MYDBCONNSTRING));
            app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
            app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);

            app.UseOAuthBearerTokens(new OAuthAuthorizationServerOptions
            {
                 Provider = new ApplicationAuthProvider(),
                 AllowInsecureHttp = true,
                 TokenEndpointPath = new PathString("/Authenticate")
            });
        }
    }
}

【问题讨论】:

  • 或许你可以使用OnResponseSignIn
  • 感谢大卫的建议。我不确定这是否可行,因为我们使用的是 OAuthBearerTokens 而不是 cookie。
  • 那么你的 OAuth 中间件是如何设置的,你能展示一下这段代码吗?
  • 我已经用 OAuth 设置代码更新了问题。

标签: c# asp.net api authentication delegatinghandler


【解决方案1】:

您正在安装OWIN middleware 以在 WebAPI 中间件之前颁发令牌。

 app.UseOAuthBearerTokens(new OAuthAuthorizationServerOptions
     {
         Provider = new ApplicationAuthProvider(),
         AllowInsecureHttp = true,
         TokenEndpointPath = new PathString("/Authenticate")
     });

您尝试用于记录请求的 DelegatingHandler 是 Web API 中间件的一部分,并且永远无法到达,因为发出令牌的中间件会处理请求并且不会在管道中进一步调用中间件。

不要使用DelegatingHandler,而是使用以下中间件并将其安装在令牌中间件之前。

public class RequestLoggerMiddleware
{
    private readonly Func<IDictionary<string, object>, Task> _next;
    private readonly ILogger _logger;

    public RequestLoggerMiddleware(
        Func<IDictionary<string, object>, Task> next, 
        ILogger logger)
    {
        _next = next;
        _logger = logger;
    }

    public Task Invoke(IDictionary<string, object> environment)
    {
        var context = new OwinContext(environment);

        _logger.Write($"{context.Request.Method} {context.Request.Uri.AbsoluteUri}");
        var result = _next.Invoke(environment);
        _logger.Write($"Status code: {context.Response.StatusCode}");

        return result;
    }
}

要安装中间件,只需在Startup.cs 中的app.UseOAuthBearerTokens 语句之前插入语句:app.Use(typeof (RequestLoggerMiddleware));

【讨论】:

  • 有道理。您能否指出一个资源,该资源显示如何在 OAuth 中间件组件之前注册“RequestLoggerMiddleware”?
  • @thiag0 只需在app.UseOAuthBearerTokens 语句之前插入语句:app.Use(typeof (RequestLoggerMiddleware));
  • 使用这种方式时,读取请求内容的正确方法是什么,等待响应被处理,这样也可以被记录?
  • @thiag0 我已经更新了我的答案以记录响应代码。 HTH。
  • 酷,谢谢。是否有一些特殊的方式需要我们读取 context.Request.Body 和 context.Response.Body?例如,在 DelegatingHandler 中,如果我们直接访问缓冲区,它会使链中的其他处理程序无法使用它,因此我们必须使用 HttpRequestMessage.Content.ReadAsByteArrayAsync() 将其复制到内部缓冲区。在这种情况下我们是否必须采用相同的方法?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-09
  • 2015-01-27
  • 1970-01-01
  • 2018-06-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多